├── .gitignore ├── assets └── fonts │ └── FiraSans-Medium.ttf ├── src ├── serialize │ ├── mod.rs │ ├── test.rs │ ├── error.rs │ ├── serializer.rs │ └── deserializer.rs ├── random.rs ├── lib.rs └── bin │ ├── verifier.rs │ └── gui.rs ├── c ├── makefile └── random.c ├── cpp ├── makefile └── random.cpp ├── Cargo.toml ├── verifier.sh ├── README.md └── Cargo.lock /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | .idea -------------------------------------------------------------------------------- /assets/fonts/FiraSans-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agluszak/mimuw-sik-2022-public/HEAD/assets/fonts/FiraSans-Medium.ttf -------------------------------------------------------------------------------- /src/serialize/mod.rs: -------------------------------------------------------------------------------- 1 | pub use error::*; 2 | 3 | pub mod deserializer; 4 | pub mod error; 5 | pub mod serializer; 6 | mod test; 7 | -------------------------------------------------------------------------------- /c/makefile: -------------------------------------------------------------------------------- 1 | CFLAGS = -Wall -Wextra -Wconversion -Werror -g -std=gnu17 2 | CC = gcc 3 | 4 | random: random.o 5 | $(CC) $(CFLAGS) -o $@ random.o 6 | 7 | clean: 8 | -rm -f *.o random 9 | 10 | .c.o: 11 | $(CC) $(CFLAGS) -c $< 12 | -------------------------------------------------------------------------------- /cpp/makefile: -------------------------------------------------------------------------------- 1 | CFLAGS = -Wall -Wextra -Wconversion -Werror -g -std=gnu++20 2 | CC = g++ 3 | 4 | random: random.o 5 | $(CC) $(CFLAGS) -o $@ random.o 6 | 7 | clean: 8 | -rm -f *.o random 9 | 10 | .cpp.o: 11 | $(CC) $(CFLAGS) -c $< 12 | -------------------------------------------------------------------------------- /cpp/random.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() { 6 | std::uint32_t seed = 1234; 7 | 8 | std::minstd_rand random(seed); 9 | for (int i = 0; i < 10; i++) { 10 | std::cout << i << " - " << random() << std::endl; 11 | } 12 | 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /c/random.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | uint32_t next_random(uint32_t previous) { 5 | return (uint32_t) (((uint64_t) previous * 48271) % 2147483647); 6 | } 7 | 8 | int main(void) { 9 | uint32_t seed = 1234; 10 | uint32_t random = next_random(seed); 11 | for (int i = 0; i < 10; i++) { 12 | printf("%d - %u\n", i, random); 13 | random = next_random(random); 14 | } 15 | 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "robots" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | bevy = { version = "0.7", features = ["dynamic"] } 8 | bevy_prototype_lyon = "0.5" 9 | clap = { version = "3", features = ["derive"] } 10 | tracing = "0.1" 11 | tracing-subscriber = "0.3" 12 | tracing-tree = "0.2" 13 | lazy_static = "1" 14 | serde = "1" 15 | serde_json = "1" 16 | byteorder = "1" 17 | thiserror = "1" 18 | itertools = "0.10" 19 | rand = "0.8" 20 | crossbeam-channel = "0.5" 21 | -------------------------------------------------------------------------------- /src/serialize/test.rs: -------------------------------------------------------------------------------- 1 | #![cfg(test)] 2 | 3 | use crate::serialize::deserializer::from_bytes; 4 | use crate::serialize::serializer::to_bytes; 5 | use crate::{BombId, Event, PlayerId, Position, ServerMessage}; 6 | 7 | #[test] 8 | fn server_message_events() { 9 | let sm = ServerMessage::Turn { 10 | turn: 44, 11 | events: vec![ 12 | Event::PlayerMoved { 13 | id: PlayerId(3), 14 | position: Position(2, 4), 15 | }, 16 | Event::PlayerMoved { 17 | id: PlayerId(4), 18 | position: Position(3, 5), 19 | }, 20 | Event::BombPlaced { 21 | id: BombId(5), 22 | position: Position(5, 7), 23 | }, 24 | ], 25 | }; 26 | let bytes = to_bytes(&sm); 27 | println!("{:?}", bytes); 28 | let sm2 = from_bytes::(&to_bytes(&sm)).unwrap(); 29 | assert_eq!(sm, sm2); 30 | } 31 | -------------------------------------------------------------------------------- /src/random.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug, Clone, Default)] 2 | pub struct Random { 3 | seed: u32, 4 | } 5 | 6 | impl Random { 7 | pub fn new(seed: u32) -> Random { 8 | Random { seed } 9 | } 10 | 11 | pub fn next_u32(&mut self) -> u32 { 12 | let seed = self.seed; 13 | let seed_u64 = seed as u64; 14 | let value = (seed_u64 * 48271) % 2147483647; 15 | self.seed = value as u32; 16 | self.seed 17 | } 18 | 19 | pub fn range_u16(&mut self, min: u16, max: u16) -> u16 { 20 | let min = min as u32; 21 | let max = max as u32; 22 | let range = max - min; 23 | let value = self.next_u32(); 24 | let value_in_range = (value % range) + min; 25 | (value_in_range % (u16::MAX as u32)) as u16 26 | } 27 | } 28 | 29 | #[cfg(test)] 30 | mod test { 31 | use super::*; 32 | 33 | #[test] 34 | fn seed_1234() { 35 | let mut random = Random::new(1234); 36 | assert_eq!(random.next_u32(), 59566414); 37 | assert_eq!(random.next_u32(), 1997250508); 38 | assert_eq!(random.next_u32(), 148423250); 39 | assert_eq!(random.next_u32(), 533254358); 40 | assert_eq!(random.next_u32(), 982122076); 41 | assert_eq!(random.next_u32(), 165739424); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/serialize/error.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::Display; 2 | 3 | use serde::{de, ser}; 4 | use thiserror::Error; 5 | 6 | pub type Result = std::result::Result; 7 | 8 | #[derive(Debug, Error)] 9 | pub enum DeserError { 10 | #[error("Invalid enum variant: {0}")] 11 | InvalidEnumVariant(u8), 12 | #[error("Expected unit (byte '0')")] 13 | InvalidUnit, 14 | #[error("Expected option (byte '0' or '1')")] 15 | InvalidOption, 16 | #[error("Expected boolean (byte '0' or '1')")] 17 | InvalidBool, 18 | #[error("Length of the sequence must be known")] 19 | UnknownLength, 20 | #[error("Not all bytes were processed")] 21 | TrailingData, 22 | #[error("Encoding failed: {0}")] 23 | Encoding(String), 24 | #[error("Decoding failed: {0}")] 25 | Decoding(String), 26 | #[error("IO error: {0}")] 27 | Io(#[from] std::io::Error), 28 | #[error("UTF-8 error: {0}")] 29 | Utf8(#[from] std::str::Utf8Error), 30 | #[error("Integer conversion error: {0}")] 31 | Int(#[from] std::num::TryFromIntError), 32 | } 33 | 34 | impl ser::Error for DeserError { 35 | fn custom(msg: T) -> Self { 36 | DeserError::Encoding(msg.to_string()) 37 | } 38 | } 39 | 40 | impl de::Error for DeserError { 41 | fn custom(msg: T) -> Self { 42 | DeserError::Decoding(msg.to_string()) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /verifier.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | function check_executable() { 4 | EXECUTABLE=$1 5 | if [ -f "$EXECUTABLE" ]; then 6 | echo "$EXECUTABLE executable found" 7 | ANYTHING_BUILT=true 8 | 9 | ./"$EXECUTABLE" >/dev/null 2>&1 10 | if [ $? -ne 1 ]; then 11 | echo "$EXECUTABLE should fail with exit code 1 when no arguments are given" 12 | fi 13 | 14 | OUTPUT=$(mktemp) 15 | ./"$EXECUTABLE" -h >"$OUTPUT" 2>/dev/null 16 | if [ $? -ne 0 ]; then 17 | echo "$EXECUTABLE should exit with exit code 0 when -h is given" 18 | fi 19 | 20 | # Check if output is non-empty 21 | if [ ! -s "$OUTPUT" ]; then 22 | echo "$EXECUTABLE should output help text to stdout when -h is given" 23 | fi 24 | fi 25 | } 26 | 27 | function verify() { 28 | if [ -z "$1" ]; then 29 | echo "Usage: $0 " 30 | exit 1 31 | fi 32 | if [ ! -f "$1" ]; then 33 | echo "File $1 does not exist" 34 | exit 1 35 | fi 36 | if [ ! -r "$1" ]; then 37 | echo "File $1 is not readable" 38 | exit 1 39 | fi 40 | if [ ! -s "$1" ]; then 41 | echo "File $1 is empty" 42 | exit 1 43 | fi 44 | 45 | # Check if file is a valid zip file 46 | unzip -t "$1" >/dev/null 47 | if [ $? -ne 0 ]; then 48 | echo "File $1 is not a valid zip file" 49 | exit 1 50 | fi 51 | 52 | # Create a temp directory 53 | TEMP_DIR=$(mktemp -d) 54 | 55 | # Unzip to the temp directory 56 | unzip -q "$1" -d "$TEMP_DIR" 57 | pushd "$TEMP_DIR" >/dev/null || exit 1 58 | 59 | SERVER_EXECUTABLE="robots-server" 60 | CLIENT_EXECUTABLE="robots-client" 61 | 62 | # Check if cmake works 63 | cmake . >/dev/null 2>&1 64 | if [ $? -ne 0 ]; then 65 | echo "CMake failed, trying make" 66 | fi 67 | 68 | ALL_OK=true 69 | 70 | # Check if there is a makefile 71 | 72 | ls | grep -i "makefile" >/dev/null 2>&1 73 | if [ $? -eq 0 ]; then 74 | TEMP_FILE=$(mktemp) 75 | # Check if the solution can be built using `make` 76 | make SHELL="/bin/bash -x" >"$TEMP_FILE" 2>&1 77 | STATUS=$? 78 | 79 | REQUIRED_FLAGS=("-Wall" "-Wextra" "-Wconversion" "-Werror" "-O2") 80 | STANDARD_FLAG=("-std=gnu++20" "-std=gnu17") 81 | 82 | for flag in "${REQUIRED_FLAGS[@]}"; do 83 | if ! grep -q -- "$flag" "$TEMP_FILE"; then 84 | echo "Missing flag $flag" 85 | ALL_OK=false 86 | fi 87 | done 88 | 89 | FOUND_STANDARD_FLAG=false 90 | for flag in "${STANDARD_FLAG[@]}"; do 91 | if grep -q -- "$flag" "$TEMP_FILE"; then 92 | FOUND_STANDARD_FLAG=true 93 | fi 94 | done 95 | 96 | if [ "$FOUND_STANDARD_FLAG" = false ]; then 97 | echo "Missing flag -std=gnu17 or -std=gnu++20" 98 | ALL_OK=false 99 | fi 100 | 101 | # Check if there were warnings or errors during build 102 | grep "note:" "$TEMP_FILE" 103 | if [ $? -eq 0 ]; then 104 | echo "Notes during build" 105 | ALL_OK=false 106 | fi 107 | 108 | grep "warning:" "$TEMP_FILE" 109 | if [ $? -eq 0 ]; then 110 | echo "Warnings during build" 111 | ALL_OK=false 112 | fi 113 | 114 | grep "error:" "$TEMP_FILE" 115 | if [ $? -eq 0 ]; then 116 | echo "Errors during build" 117 | ALL_OK=false 118 | fi 119 | 120 | if [ $STATUS -eq 0 ]; then 121 | ANYTHING_BUILT=false 122 | check_executable "$SERVER_EXECUTABLE" 123 | check_executable "$CLIENT_EXECUTABLE" 124 | 125 | if [ "$ANYTHING_BUILT" = false ]; then 126 | echo "Solution was built, but no executable was found. Are the names correct?" 127 | ALL_OK=false 128 | fi 129 | else 130 | echo "Solution could not be built" 131 | ALL_OK=false 132 | fi 133 | else 134 | echo "No makefile found. Is the solution correctly packed?" 135 | ALL_OK=false 136 | fi 137 | 138 | popd >/dev/null || exit 1 139 | if [ "$ALL_OK" = true ]; then 140 | echo "Solution is valid" 141 | exit 0 142 | else 143 | echo "Solution is not valid" 144 | exit 1 145 | fi 146 | } 147 | 148 | verify "$@" 149 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | use std::collections::{BTreeMap, HashSet}; 3 | use std::net::SocketAddr; 4 | 5 | pub mod random; 6 | pub mod serialize; 7 | 8 | pub const MAX_UDP_LENGTH: usize = 65_535; 9 | 10 | #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] 11 | pub enum InputMessage { 12 | PlaceBomb, 13 | PlaceBlock, 14 | Move { direction: Direction }, 15 | } 16 | 17 | #[allow(clippy::large_enum_variant)] 18 | #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] 19 | pub enum DisplayMessage { 20 | Lobby { 21 | server_name: String, 22 | players_count: u8, 23 | size_x: u16, 24 | size_y: u16, 25 | game_length: u16, 26 | explosion_radius: u16, 27 | bomb_timer: u16, 28 | players: BTreeMap, 29 | }, 30 | Game { 31 | server_name: String, 32 | size_x: u16, 33 | size_y: u16, 34 | game_length: u16, 35 | turn: u16, 36 | players: BTreeMap, 37 | player_positions: BTreeMap, 38 | blocks: HashSet, 39 | bombs: HashSet, 40 | explosions: HashSet, 41 | scores: BTreeMap, 42 | }, 43 | } 44 | 45 | #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] 46 | pub enum ClientMessage { 47 | Join { name: String }, 48 | PlaceBomb, 49 | PlaceBlock, 50 | Move { direction: Direction }, 51 | } 52 | 53 | impl From for ClientMessage { 54 | fn from(input_message: InputMessage) -> ClientMessage { 55 | match input_message { 56 | InputMessage::PlaceBomb => ClientMessage::PlaceBomb, 57 | InputMessage::PlaceBlock => ClientMessage::PlaceBlock, 58 | InputMessage::Move { direction } => ClientMessage::Move { direction }, 59 | } 60 | } 61 | } 62 | 63 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] 64 | pub enum Direction { 65 | Up, 66 | Right, 67 | Down, 68 | Left, 69 | } 70 | 71 | #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] 72 | pub struct Bomb { 73 | pub position: Position, 74 | pub timer: u16, 75 | } 76 | 77 | #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] 78 | pub enum ServerMessage { 79 | Hello { 80 | server_name: String, 81 | players_count: u8, 82 | size_x: u16, 83 | size_y: u16, 84 | game_length: u16, 85 | explosion_radius: u16, 86 | bomb_timer: u16, 87 | }, 88 | AcceptedPlayer { 89 | id: PlayerId, 90 | player: Player, 91 | }, 92 | GameStarted { 93 | players: BTreeMap, 94 | }, 95 | Turn { 96 | turn: u16, 97 | events: Vec, 98 | }, 99 | GameEnded { 100 | scores: BTreeMap, 101 | }, 102 | } 103 | 104 | #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Default)] 105 | pub struct Score { 106 | pub deaths: u32, 107 | } 108 | 109 | #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] 110 | pub struct Player { 111 | pub name: String, 112 | pub socket_addr: SocketAddr, 113 | } 114 | 115 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] 116 | pub struct Position(pub u16, pub u16); 117 | 118 | #[derive( 119 | Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default, Ord, PartialOrd, 120 | )] 121 | pub struct PlayerId(pub u8); 122 | 123 | #[derive( 124 | Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default, Ord, PartialOrd, 125 | )] 126 | pub struct BombId(pub u32); 127 | 128 | #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] 129 | pub enum Event { 130 | BombPlaced { 131 | id: BombId, 132 | position: Position, 133 | }, 134 | BombExploded { 135 | id: BombId, 136 | killed: Vec, 137 | blocks_destroyed: HashSet, 138 | }, 139 | PlayerMoved { 140 | id: PlayerId, 141 | position: Position, 142 | }, 143 | BlockPlaced { 144 | position: Position, 145 | }, 146 | } 147 | -------------------------------------------------------------------------------- /src/bin/verifier.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::Debug; 2 | 3 | use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, TcpListener, TcpStream, UdpSocket}; 4 | use std::str::FromStr; 5 | 6 | use clap::Parser; 7 | use lazy_static::lazy_static; 8 | use serde::de::DeserializeOwned; 9 | 10 | use tracing::{error, info, Level}; 11 | 12 | use robots::serialize::deserializer::Deserializer; 13 | use robots::serialize::{deserializer, DeserError}; 14 | use robots::{ClientMessage, DisplayMessage, InputMessage, ServerMessage, MAX_UDP_LENGTH}; 15 | 16 | #[derive(Parser, Debug, Clone)] 17 | #[clap(author, version, about, long_about = None)] 18 | struct Args { 19 | #[clap(short, long)] 20 | port: u16, 21 | 22 | #[clap(short, long)] 23 | udp: bool, 24 | 25 | #[clap(short, long)] 26 | message_type: MessageType, 27 | } 28 | 29 | #[derive(Debug, Clone, PartialEq, Eq)] 30 | enum MessageType { 31 | Client, 32 | Server, 33 | Display, 34 | Input, 35 | } 36 | 37 | impl FromStr for MessageType { 38 | type Err = String; 39 | 40 | fn from_str(s: &str) -> Result { 41 | match s { 42 | "client" => Ok(MessageType::Client), 43 | "server" => Ok(MessageType::Server), 44 | "display" => Ok(MessageType::Display), 45 | "input" => Ok(MessageType::Input), 46 | _ => Err(format!("Unknown message type: {}", s)), 47 | } 48 | } 49 | } 50 | 51 | lazy_static! { 52 | static ref ARGS: Args = Args::parse(); 53 | } 54 | 55 | fn deserialize_message_from_buffer( 56 | message: &[u8], 57 | address: SocketAddr, 58 | ) { 59 | match deserializer::from_bytes::(message) { 60 | Ok(message) => info!(addr = ?address, message = ?message), 61 | Err(err) => error!(addr = ?address, error = ?err), 62 | } 63 | } 64 | 65 | fn deserialize_message_from_stream( 66 | deserialize: &mut Deserializer, 67 | address: SocketAddr, 68 | ) { 69 | loop { 70 | match deserialize.deserialize::() { 71 | Ok(message) => info!(addr = ?address, message = ?message), 72 | Err(DeserError::Io(io)) if io.kind() == std::io::ErrorKind::UnexpectedEof => { 73 | break; 74 | } 75 | Err(err) => { 76 | error!(addr = ?address, error = ?err); 77 | break; 78 | } 79 | } 80 | } 81 | } 82 | 83 | fn main() { 84 | tracing_subscriber::fmt::fmt() 85 | .with_max_level(Level::TRACE) 86 | .init(); 87 | 88 | info!(args = ?ARGS.clone()); 89 | 90 | let server_address = SocketAddr::from((Ipv6Addr::UNSPECIFIED, ARGS.port)); 91 | 92 | if ARGS.udp { 93 | let udp_server = UdpSocket::bind(server_address).unwrap(); 94 | let mut buffer = [0u8; MAX_UDP_LENGTH]; 95 | loop { 96 | match udp_server.recv_from(&mut buffer) { 97 | Ok((size, addr)) => { 98 | let bytes = &buffer[..size]; 99 | match ARGS.message_type { 100 | MessageType::Client => { 101 | deserialize_message_from_buffer::(bytes, addr) 102 | } 103 | MessageType::Server => { 104 | deserialize_message_from_buffer::(bytes, addr) 105 | } 106 | MessageType::Display => { 107 | deserialize_message_from_buffer::(bytes, addr) 108 | } 109 | MessageType::Input => { 110 | deserialize_message_from_buffer::(bytes, addr) 111 | } 112 | }; 113 | } 114 | Err(e) => { 115 | error!("Error: {}", e); 116 | } 117 | } 118 | } 119 | } else { 120 | let tcp_server = TcpListener::bind(server_address).unwrap(); 121 | loop { 122 | match tcp_server.accept() { 123 | Ok((stream, addr)) => { 124 | info!(message = "Received TCP connection", addr = ?addr); 125 | stream.set_nodelay(true).unwrap(); 126 | let mut deserializer = Deserializer::new(stream); 127 | match ARGS.message_type { 128 | MessageType::Client => deserialize_message_from_stream::( 129 | &mut deserializer, 130 | addr, 131 | ), 132 | MessageType::Server => deserialize_message_from_stream::( 133 | &mut deserializer, 134 | addr, 135 | ), 136 | MessageType::Display => deserialize_message_from_stream::( 137 | &mut deserializer, 138 | addr, 139 | ), 140 | MessageType::Input => { 141 | deserialize_message_from_stream::(&mut deserializer, addr) 142 | } 143 | } 144 | } 145 | Err(e) => { 146 | error!("Error when connecting: {}", e); 147 | } 148 | } 149 | } 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /src/serialize/serializer.rs: -------------------------------------------------------------------------------- 1 | use byteorder::{BigEndian, NetworkEndian, WriteBytesExt}; 2 | use serde::{ser, Serialize}; 3 | 4 | use crate::serialize::{DeserError, Result}; 5 | 6 | pub struct Serializer { 7 | output: Vec, 8 | } 9 | 10 | pub fn to_bytes(value: T) -> Vec { 11 | let mut serializer = Serializer { output: Vec::new() }; 12 | value.serialize(&mut serializer).unwrap(); // Serialization in our protocol is infallible 13 | serializer.output 14 | } 15 | 16 | impl<'a> ser::Serializer for &'a mut Serializer { 17 | type Ok = (); 18 | type Error = DeserError; 19 | type SerializeSeq = Self; 20 | type SerializeTuple = Self; 21 | type SerializeTupleStruct = Self; 22 | type SerializeTupleVariant = Self; 23 | type SerializeMap = Self; 24 | type SerializeStruct = Self; 25 | type SerializeStructVariant = Self; 26 | 27 | fn serialize_bool(self, v: bool) -> Result<()> { 28 | self.serialize_u8(if v { 1 } else { 0 })?; 29 | Ok(()) 30 | } 31 | 32 | fn serialize_i8(self, v: i8) -> Result<()> { 33 | self.output.write_i8(v)?; 34 | Ok(()) 35 | } 36 | 37 | fn serialize_i16(self, v: i16) -> Result<()> { 38 | self.output.write_i16::(v)?; 39 | Ok(()) 40 | } 41 | 42 | fn serialize_i32(self, v: i32) -> Result<()> { 43 | self.output.write_i32::(v)?; 44 | Ok(()) 45 | } 46 | 47 | fn serialize_i64(self, v: i64) -> Result<()> { 48 | self.output.write_i64::(v)?; 49 | Ok(()) 50 | } 51 | 52 | fn serialize_u8(self, v: u8) -> Result<()> { 53 | self.output.write_u8(v)?; 54 | Ok(()) 55 | } 56 | 57 | fn serialize_u16(self, v: u16) -> Result<()> { 58 | self.output.write_u16::(v)?; 59 | Ok(()) 60 | } 61 | 62 | fn serialize_u32(self, v: u32) -> Result<()> { 63 | self.output.write_u32::(v)?; 64 | Ok(()) 65 | } 66 | 67 | fn serialize_u64(self, v: u64) -> Result<()> { 68 | self.output.write_u64::(v)?; 69 | Ok(()) 70 | } 71 | 72 | fn serialize_f32(self, _v: f32) -> Result<()> { 73 | unimplemented!() 74 | } 75 | 76 | fn serialize_f64(self, _v: f64) -> Result<()> { 77 | unimplemented!() 78 | } 79 | 80 | fn serialize_char(self, _v: char) -> Result<()> { 81 | unimplemented!() 82 | } 83 | 84 | fn serialize_str(self, v: &str) -> Result<()> { 85 | self.serialize_bytes(v.as_bytes()) 86 | } 87 | 88 | fn serialize_bytes(self, v: &[u8]) -> Result<()> { 89 | let length: u8 = v.len().try_into()?; 90 | self.serialize_u8(length)?; 91 | self.output.extend_from_slice(v); 92 | Ok(()) 93 | } 94 | 95 | fn serialize_none(self) -> Result<()> { 96 | self.serialize_u8(0)?; 97 | Ok(()) 98 | } 99 | 100 | fn serialize_some(self, value: &T) -> Result<()> 101 | where 102 | T: Serialize, 103 | { 104 | self.serialize_u8(1)?; 105 | value.serialize(self)?; 106 | Ok(()) 107 | } 108 | 109 | fn serialize_unit(self) -> Result<()> { 110 | self.serialize_u8(0)?; 111 | Ok(()) 112 | } 113 | 114 | fn serialize_unit_struct(self, _name: &'static str) -> Result<()> { 115 | self.serialize_unit() 116 | } 117 | 118 | fn serialize_unit_variant( 119 | self, 120 | _name: &'static str, 121 | variant_index: u32, 122 | _variant: &'static str, 123 | ) -> Result<()> { 124 | let variant_index: u8 = variant_index.try_into()?; 125 | self.serialize_u8(variant_index)?; 126 | Ok(()) 127 | } 128 | 129 | fn serialize_newtype_struct(self, _name: &'static str, value: &T) -> Result<()> 130 | where 131 | T: Serialize, 132 | { 133 | value.serialize(self) 134 | } 135 | 136 | fn serialize_newtype_variant( 137 | self, 138 | _name: &'static str, 139 | variant_index: u32, 140 | _variant: &'static str, 141 | value: &T, 142 | ) -> Result<()> 143 | where 144 | T: Serialize, 145 | { 146 | let variant_index: u8 = variant_index.try_into()?; 147 | self.serialize_u8(variant_index)?; 148 | value.serialize(self) 149 | } 150 | 151 | fn serialize_seq(self, len: Option) -> Result { 152 | if let Some(len) = len { 153 | let len: u32 = len.try_into()?; 154 | self.serialize_u32(len)?; 155 | Ok(self) 156 | } else { 157 | Err(DeserError::UnknownLength) 158 | } 159 | } 160 | 161 | fn serialize_tuple(self, _len: usize) -> Result { 162 | Ok(self) 163 | } 164 | 165 | fn serialize_tuple_struct( 166 | self, 167 | _name: &'static str, 168 | _len: usize, 169 | ) -> Result { 170 | Ok(self) 171 | } 172 | 173 | fn serialize_tuple_variant( 174 | self, 175 | _name: &'static str, 176 | variant_index: u32, 177 | _variant: &'static str, 178 | _len: usize, 179 | ) -> Result { 180 | self.serialize_struct_variant(_name, variant_index, _variant, _len) 181 | } 182 | 183 | fn serialize_map(self, len: Option) -> Result { 184 | self.serialize_seq(len) 185 | } 186 | 187 | fn serialize_struct(self, _name: &'static str, _len: usize) -> Result { 188 | Ok(self) 189 | } 190 | 191 | fn serialize_struct_variant( 192 | self, 193 | _name: &'static str, 194 | variant_index: u32, 195 | _variant: &'static str, 196 | _len: usize, 197 | ) -> Result { 198 | let variant_index: u8 = variant_index.try_into()?; 199 | self.serialize_u8(variant_index)?; 200 | Ok(self) 201 | } 202 | } 203 | 204 | impl<'a> ser::SerializeSeq for &'a mut Serializer { 205 | type Ok = (); 206 | type Error = DeserError; 207 | 208 | // Serialize a single element of the sequence. 209 | fn serialize_element(&mut self, value: &T) -> Result<()> 210 | where 211 | T: ?Sized + Serialize, 212 | { 213 | value.serialize(&mut **self) 214 | } 215 | 216 | fn end(self) -> Result<()> { 217 | Ok(()) 218 | } 219 | } 220 | 221 | impl<'a> ser::SerializeTuple for &'a mut Serializer { 222 | type Ok = (); 223 | type Error = DeserError; 224 | 225 | fn serialize_element(&mut self, value: &T) -> Result<()> 226 | where 227 | T: ?Sized + Serialize, 228 | { 229 | value.serialize(&mut **self) 230 | } 231 | 232 | fn end(self) -> Result<()> { 233 | Ok(()) 234 | } 235 | } 236 | 237 | impl<'a> ser::SerializeTupleStruct for &'a mut Serializer { 238 | type Ok = (); 239 | type Error = DeserError; 240 | 241 | fn serialize_field(&mut self, value: &T) -> Result<()> 242 | where 243 | T: ?Sized + Serialize, 244 | { 245 | value.serialize(&mut **self) 246 | } 247 | 248 | fn end(self) -> Result<()> { 249 | Ok(()) 250 | } 251 | } 252 | 253 | impl<'a> ser::SerializeTupleVariant for &'a mut Serializer { 254 | type Ok = (); 255 | type Error = DeserError; 256 | 257 | fn serialize_field(&mut self, value: &T) -> Result<()> 258 | where 259 | T: ?Sized + Serialize, 260 | { 261 | value.serialize(&mut **self) 262 | } 263 | 264 | fn end(self) -> Result<()> { 265 | Ok(()) 266 | } 267 | } 268 | 269 | impl<'a> ser::SerializeMap for &'a mut Serializer { 270 | type Ok = (); 271 | type Error = DeserError; 272 | 273 | fn serialize_key(&mut self, key: &T) -> Result<()> 274 | where 275 | T: ?Sized + Serialize, 276 | { 277 | key.serialize(&mut **self) 278 | } 279 | 280 | fn serialize_value(&mut self, value: &T) -> Result<()> 281 | where 282 | T: ?Sized + Serialize, 283 | { 284 | value.serialize(&mut **self) 285 | } 286 | 287 | fn end(self) -> Result<()> { 288 | Ok(()) 289 | } 290 | } 291 | 292 | impl<'a> ser::SerializeStruct for &'a mut Serializer { 293 | type Ok = (); 294 | type Error = DeserError; 295 | 296 | fn serialize_field(&mut self, _key: &'static str, value: &T) -> Result<()> 297 | where 298 | T: ?Sized + Serialize, 299 | { 300 | value.serialize(&mut **self) 301 | } 302 | 303 | fn end(self) -> Result<()> { 304 | Ok(()) 305 | } 306 | } 307 | 308 | impl<'a> ser::SerializeStructVariant for &'a mut Serializer { 309 | type Ok = (); 310 | type Error = DeserError; 311 | 312 | fn serialize_field(&mut self, _key: &'static str, value: &T) -> Result<()> 313 | where 314 | T: ?Sized + Serialize, 315 | { 316 | value.serialize(&mut **self) 317 | } 318 | 319 | fn end(self) -> Result<()> { 320 | Ok(()) 321 | } 322 | } 323 | 324 | #[cfg(test)] 325 | mod test { 326 | use super::*; 327 | 328 | #[test] 329 | fn test_serialize_u8() { 330 | let value: u8 = 0xFF; 331 | let serialized = to_bytes(&value); 332 | assert_eq!(serialized, [0xFF]); 333 | } 334 | 335 | #[test] 336 | fn test_serialize_u16() { 337 | let value: u16 = 0x1234; 338 | let serialized = to_bytes(&value); 339 | assert_eq!(serialized, [0x12, 0x34]); 340 | } 341 | 342 | #[test] 343 | fn test_serialize_u32() { 344 | let value: u32 = 0x12345678; 345 | let serialized = to_bytes(&value); 346 | assert_eq!(serialized, [0x12, 0x34, 0x56, 0x78]); 347 | } 348 | 349 | #[test] 350 | fn test_serialize_enum() { 351 | #[derive(Serialize)] 352 | enum Message { 353 | Hello(String), 354 | Goodbye(String), 355 | } 356 | 357 | let message = Message::Hello("world".to_string()); 358 | let serialized = to_bytes(&message); 359 | assert_eq!(serialized, [0, 5, b'w', b'o', b'r', b'l', b'd']); 360 | 361 | let message = Message::Goodbye("worlds".to_string()); 362 | let serialized = to_bytes(&message); 363 | assert_eq!(serialized, [1, 6, b'w', b'o', b'r', b'l', b'd', b's']); 364 | } 365 | 366 | #[test] 367 | fn test_serialize_struct() { 368 | #[derive(Serialize)] 369 | struct Message { 370 | message: String, 371 | } 372 | 373 | let message = Message { 374 | message: "hello".to_string(), 375 | }; 376 | let serialized = to_bytes(&message); 377 | assert_eq!(serialized, [5, b'h', b'e', b'l', b'l', b'o']); 378 | } 379 | 380 | #[test] 381 | fn test_serialize_nested_enum() { 382 | #[derive(Serialize)] 383 | enum Message { 384 | Hello, 385 | Goodbye, 386 | } 387 | 388 | #[derive(Serialize)] 389 | enum NestedMessage { 390 | Variant1(Message), 391 | Variant2 { message: Message, num: u16 }, 392 | } 393 | 394 | let message = NestedMessage::Variant1(Message::Hello); 395 | let serialized = to_bytes(&message); 396 | assert_eq!(serialized, [0, 0]); 397 | 398 | let message = NestedMessage::Variant1(Message::Goodbye); 399 | let serialized = to_bytes(&message); 400 | assert_eq!(serialized, [0, 1]); 401 | 402 | let message = NestedMessage::Variant2 { 403 | message: Message::Hello, 404 | num: 0x1234, 405 | }; 406 | let serialized = to_bytes(&message); 407 | assert_eq!(serialized, [1, 0, 0x12, 0x34]); 408 | } 409 | 410 | #[test] 411 | fn test_serialize_vec() { 412 | #[derive(Serialize)] 413 | enum Message { 414 | Hello(String), 415 | Goodbye, 416 | } 417 | let vec = vec![ 418 | Message::Hello("world".to_string()), 419 | Message::Goodbye, 420 | Message::Hello("something".to_string()), 421 | ]; 422 | let serialized = to_bytes(&vec); 423 | assert_eq!( 424 | serialized, 425 | [ 426 | 0, 0, 0, 3, 0, 5, b'w', b'o', b'r', b'l', b'd', 1, 0, 9, b's', b'o', b'm', b'e', 427 | b't', b'h', b'i', b'n', b'g' 428 | ] 429 | ); 430 | } 431 | 432 | #[test] 433 | fn test_serialize_map() { 434 | #[derive(Serialize)] 435 | enum Message { 436 | Hello(String), 437 | Goodbye, 438 | } 439 | let map = vec![ 440 | ("hello".to_string(), Message::Hello("world".to_string())), 441 | ("goodbye".to_string(), Message::Goodbye), 442 | ]; 443 | let serialized = to_bytes(&map); 444 | assert_eq!( 445 | serialized, 446 | [ 447 | 0, 0, 0, 2, 5, b'h', b'e', b'l', b'l', b'o', 0, 5, b'w', b'o', b'r', b'l', b'd', 7, 448 | b'g', b'o', b'o', b'd', b'b', b'y', b'e', 1 449 | ] 450 | ); 451 | } 452 | 453 | #[test] 454 | fn test_serialize_tuple_enum() { 455 | #[derive(Serialize)] 456 | enum Message { 457 | Hello(u16, u16), 458 | Goodbye, 459 | } 460 | let vec = vec![Message::Hello(0x1234, 0x5678), Message::Goodbye]; 461 | let serialized = to_bytes(&vec); 462 | assert_eq!(serialized, [0, 0, 0, 2, 0, 0x12, 0x34, 0x56, 0x78, 1]); 463 | } 464 | 465 | #[test] 466 | fn test_serialize_tuple_struct() { 467 | #[derive(Serialize)] 468 | struct Message(u16, u16); 469 | let vec = vec![Message(0x1234, 0x5678), Message(0x9abc, 0xdef0)]; 470 | let serialized = to_bytes(&vec); 471 | assert_eq!( 472 | serialized, 473 | [0, 0, 0, 2, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0] 474 | ); 475 | } 476 | } 477 | -------------------------------------------------------------------------------- /src/bin/gui.rs: -------------------------------------------------------------------------------- 1 | use bevy::input::keyboard::KeyboardInput; 2 | use bevy::prelude::*; 3 | use bevy_prototype_lyon::prelude::*; 4 | use crossbeam_channel::{bounded, Receiver}; 5 | use std::net::{Ipv6Addr, SocketAddr, ToSocketAddrs, UdpSocket}; 6 | 7 | use clap::Parser; 8 | use lazy_static::lazy_static; 9 | use robots::{DisplayMessage, InputMessage, Position, MAX_UDP_LENGTH}; 10 | use robots::serialize::{deserializer, serializer}; 11 | 12 | #[derive(Parser, Debug, Clone)] 13 | #[clap(author, version, about, long_about = None)] 14 | struct Args { 15 | #[clap(short, long, parse(try_from_str = parse_addr))] 16 | client_address: SocketAddr, 17 | 18 | #[clap(short, long)] 19 | port: u16, 20 | } 21 | 22 | fn parse_addr(s: &str) -> Result { 23 | s.to_socket_addrs() 24 | .map_err(|e| e.to_string()) 25 | .and_then(|mut iter| iter.next().ok_or_else(|| "No address found".to_string())) 26 | } 27 | 28 | lazy_static! { 29 | static ref ARGS: Args = Args::parse(); 30 | } 31 | 32 | fn main() { 33 | info!(args = ?ARGS.clone()); 34 | 35 | App::new() 36 | .insert_resource(WindowDescriptor { 37 | title: "Robots!".to_string(), 38 | width: 640., 39 | height: 480., 40 | ..default() 41 | }) 42 | .insert_resource(bevy::log::LogSettings { 43 | level: bevy::log::Level::INFO, 44 | filter: "wgpu=warn,wgpu_core=warn,bevy_ecs=info".to_string(), 45 | }) 46 | .add_event::() 47 | .add_plugins(DefaultPlugins) 48 | .add_plugin(ShapePlugin) 49 | .add_startup_system(setup) 50 | .add_system(read_stream) 51 | .add_system(draw) 52 | .add_system(send_input) 53 | .run(); 54 | } 55 | 56 | #[derive(Deref)] 57 | struct DisplayMessageReceiver(Receiver); 58 | 59 | #[derive(Deref)] 60 | struct InputMessageSender(UdpSocket); 61 | 62 | #[derive(Deref)] 63 | struct LoadedFont(Handle); 64 | 65 | fn setup(mut commands: Commands, asset_server: Res) { 66 | let socket = UdpSocket::bind(SocketAddr::from((Ipv6Addr::UNSPECIFIED, ARGS.port))).unwrap(); 67 | let socket_clone = socket.try_clone().unwrap(); 68 | 69 | commands.spawn_bundle(OrthographicCameraBundle::new_2d()); 70 | commands.spawn_bundle(UiCameraBundle::default()); 71 | 72 | let (display_tx, display_rx) = bounded::(10); 73 | std::thread::spawn(move || loop { 74 | let mut buf = Box::new([0; MAX_UDP_LENGTH]); 75 | match socket.recv_from(&mut *buf) { 76 | Ok((amt, _src)) => { 77 | let message = deserializer::from_bytes::(&buf[0..amt]); 78 | match message { 79 | Ok(message) => { 80 | info!(?message, "Received message"); 81 | display_tx.send(message).unwrap() 82 | } 83 | Err(e) => error!("{:?}", e), 84 | } 85 | } 86 | Err(e) => error!("{}", e), 87 | } 88 | }); 89 | 90 | commands.insert_resource(InputMessageSender(socket_clone)); 91 | commands.insert_resource(DisplayMessageReceiver(display_rx)); 92 | 93 | let loaded_font = asset_server.load("fonts/FiraSans-Medium.ttf"); 94 | commands.insert_resource(LoadedFont(loaded_font.clone())); 95 | 96 | let text_style = TextStyle { 97 | font: loaded_font, 98 | font_size: 25.0, 99 | color: Color::RED, 100 | }; 101 | let text_alignment = TextAlignment { 102 | vertical: VerticalAlign::Top, 103 | horizontal: HorizontalAlign::Center, 104 | }; 105 | let text = format!("Waiting for input from client ({}) on port {}", ARGS.client_address, ARGS.port); 106 | commands 107 | .spawn_bundle(Text2dBundle { 108 | text: Text::with_section(text, text_style, text_alignment), 109 | transform: Transform::from_xyz(0.0, 0.0, 1.0), 110 | ..default() 111 | }) 112 | .insert(Renderable); 113 | } 114 | 115 | // This system reads from the receiver and sends events to Bevy 116 | fn read_stream(receiver: ResMut, mut events: EventWriter) { 117 | for message in receiver.try_iter() { 118 | events.send(message); 119 | } 120 | } 121 | 122 | fn send_input( 123 | socket: ResMut, 124 | mut keyboard_input_events: EventReader, 125 | ) { 126 | for event in keyboard_input_events.iter() { 127 | if event.state.is_pressed() { 128 | let input_message: InputMessage = match event.key_code { 129 | Some(KeyCode::W | KeyCode::Up) => InputMessage::Move { 130 | direction: robots::Direction::Up, 131 | }, 132 | Some(KeyCode::A | KeyCode::Left) => InputMessage::Move { 133 | direction: robots::Direction::Left, 134 | }, 135 | Some(KeyCode::S | KeyCode::Down) => InputMessage::Move { 136 | direction: robots::Direction::Down, 137 | }, 138 | Some(KeyCode::D | KeyCode::Right) => InputMessage::Move { 139 | direction: robots::Direction::Right, 140 | }, 141 | Some(KeyCode::Space | KeyCode::J | KeyCode::Z) => InputMessage::PlaceBomb, 142 | Some(KeyCode::K | KeyCode::X) => InputMessage::PlaceBlock, 143 | _ => continue, 144 | }; 145 | info!("Sending {:?}", input_message); 146 | match socket.0.send_to(&serializer::to_bytes(input_message), ARGS.client_address) { 147 | Ok(amt) => info!("Sent {} bytes", amt), 148 | Err(e) => error!("{}", e), 149 | } 150 | } 151 | } 152 | } 153 | 154 | const COLORS: &[Color] = &[ 155 | Color::RED, 156 | Color::GREEN, 157 | Color::BLUE, 158 | Color::YELLOW, 159 | Color::CYAN, 160 | Color::PURPLE, 161 | Color::SALMON, 162 | Color::ORANGE, 163 | Color::PINK, 164 | Color::OLIVE, 165 | ]; 166 | 167 | #[derive(Component)] 168 | struct Renderable; 169 | 170 | enum SpawnType { 171 | Player(Color), 172 | Bomb, 173 | Block, 174 | Explosion, 175 | Grid, 176 | } 177 | 178 | struct Spawner { 179 | length_x: f32, 180 | length_y: f32, 181 | grid_shape: shapes::Rectangle, 182 | bomb_shape: shapes::Ellipse, 183 | player_shape: shapes::Polygon, 184 | explosion_shape: shapes::Polygon, 185 | } 186 | 187 | const GRID_DISPLAY_SIZE: f32 = 400.0; 188 | 189 | impl Spawner { 190 | fn new(size_x: u16, size_y: u16) -> Self { 191 | let length_x = GRID_DISPLAY_SIZE / size_x as f32; 192 | let length_y = GRID_DISPLAY_SIZE / size_y as f32; 193 | let grid_shape = shapes::Rectangle { 194 | extents: Vec2::new(length_x, length_y), 195 | origin: RectangleOrigin::TopLeft, 196 | }; 197 | let bomb_shape = shapes::Ellipse { 198 | radii: Vec2::new(length_x / 2.0, length_y / 2.0), 199 | center: Vec2::new(length_x / 2.0, -length_y / 2.0), 200 | }; 201 | let explosion_shape = shapes::Polygon { 202 | points: vec![ 203 | Vec2::new(0.0, -length_y), 204 | Vec2::new(length_x, 0.0), 205 | Vec2::new(length_x, -length_y), 206 | Vec2::new(0.0, 0.0), 207 | ], 208 | closed: false, 209 | }; 210 | 211 | let player_shape = shapes::Polygon { 212 | points: vec![ 213 | Vec2::new(0.0, -length_y), 214 | Vec2::new(length_x, -length_y), 215 | Vec2::new(length_x / 2.0, 0.0), 216 | ], 217 | closed: true, 218 | }; 219 | Self { 220 | grid_shape, 221 | bomb_shape, 222 | player_shape, 223 | explosion_shape, 224 | length_x, 225 | length_y, 226 | } 227 | } 228 | 229 | fn spawn(&self, commands: &mut Commands, position: Position, what: SpawnType) { 230 | let color = match what { 231 | SpawnType::Player(c) => c, 232 | SpawnType::Bomb => Color::RED, 233 | SpawnType::Block => Color::DARK_GRAY, 234 | SpawnType::Explosion => Color::BLACK, 235 | SpawnType::Grid => Color::WHITE, 236 | }; 237 | let draw_mode = DrawMode::Outlined { 238 | fill_mode: FillMode::color(color), 239 | outline_mode: StrokeMode::new(Color::BLACK, 1.0), 240 | }; 241 | let z = match what { 242 | SpawnType::Player(_) => 3.0, 243 | SpawnType::Bomb => 2.0, 244 | SpawnType::Block => 1.0, 245 | SpawnType::Explosion => 4.0, 246 | SpawnType::Grid => 0.0, 247 | }; 248 | let transform = Transform::from_xyz( 249 | position.0 as f32 * self.length_x - GRID_DISPLAY_SIZE / 2.0, 250 | position.1 as f32 * self.length_y - GRID_DISPLAY_SIZE / 2.0, 251 | z, 252 | ); 253 | let geometry = GeometryBuilder::new(); 254 | 255 | let geometry = match what { 256 | SpawnType::Player(_) => geometry.add(&self.player_shape), 257 | SpawnType::Bomb => geometry.add(&self.bomb_shape), 258 | SpawnType::Block => geometry.add(&self.grid_shape), 259 | SpawnType::Explosion => geometry.add(&self.explosion_shape), 260 | SpawnType::Grid => geometry.add(&self.grid_shape), 261 | }; 262 | let bundle = geometry.build(draw_mode, transform); 263 | 264 | commands.spawn_bundle(bundle).insert(Renderable); 265 | } 266 | } 267 | 268 | fn draw( 269 | mut commands: Commands, 270 | mut reader: EventReader, 271 | old_renderables: Query>, 272 | loaded_font: Res, 273 | ) { 274 | let text_style = TextStyle { 275 | font: loaded_font.clone(), 276 | font_size: 20.0, 277 | color: Color::WHITE, 278 | }; 279 | let text_alignment = TextAlignment { 280 | vertical: VerticalAlign::Top, 281 | horizontal: HorizontalAlign::Left, 282 | }; 283 | 284 | if let Some(event) = reader.iter().last() { 285 | for ent in old_renderables.iter() { 286 | commands.entity(ent).despawn() 287 | } 288 | 289 | info!("{}", serde_json::to_string(&event).unwrap()); 290 | 291 | match event { 292 | DisplayMessage::Lobby { 293 | server_name, 294 | players_count, 295 | size_x, 296 | size_y, 297 | game_length, 298 | explosion_radius, 299 | bomb_timer, 300 | players, 301 | } => { 302 | let players = players 303 | .iter() 304 | .map(|(id, player)| { 305 | format!("({}) {} - {}", id.0, player.name, player.socket_addr) 306 | }) 307 | .collect::(); 308 | let text = format!( 309 | "Server: {server_name}\nRequired players: {players_count}\n\ 310 | Size: {size_x}x{size_y}\nGame length: {game_length}\n\ 311 | Explosion radius: {explosion_radius}\nBomb timer: {bomb_timer}\n\ 312 | Players:\n\ 313 | {players}", 314 | ); 315 | commands 316 | .spawn_bundle(Text2dBundle { 317 | text: Text::with_section(text, text_style, text_alignment), 318 | transform: Transform::from_xyz(-300.0, 200.0, 1.0), 319 | ..default() 320 | }) 321 | .insert(Renderable); 322 | } 323 | DisplayMessage::Game { 324 | server_name, 325 | size_x, 326 | size_y, 327 | game_length, 328 | turn, 329 | players, 330 | player_positions, 331 | blocks, 332 | bombs, 333 | explosions, 334 | scores, 335 | } => { 336 | let server_info = format!("{server_name} - Turn {turn}/{game_length}"); 337 | 338 | commands 339 | .spawn_bundle(Text2dBundle { 340 | text: Text::with_section(server_info, text_style, text_alignment), 341 | transform: Transform::from_xyz(-100.0, 220.0, 1.0), 342 | ..default() 343 | }) 344 | .insert(Renderable); 345 | 346 | let colors = COLORS.iter().cycle(); 347 | let players = players 348 | .iter() 349 | .zip(colors) 350 | .flat_map(|((id, player), &color)| { 351 | // TODO: handle missing data 352 | let score = scores.get(id).cloned()?; 353 | let position = player_positions.get(id).cloned()?; 354 | Some((id, player.name.clone(), score, position, color)) 355 | }) 356 | .collect::>(); 357 | 358 | let scores_sections = players 359 | .iter() 360 | .map(|(id, name, score, _, color)| { 361 | let score = format!("{}", score.deaths); 362 | let id = id.0; 363 | let text = format!("({id}) {name}: {score}\n"); 364 | let color = *color; 365 | TextSection { 366 | value: text, 367 | style: TextStyle { 368 | font: loaded_font.clone(), 369 | font_size: 15.0, 370 | color, 371 | }, 372 | } 373 | }) 374 | .collect::>(); 375 | 376 | let scores_text = Text { 377 | sections: scores_sections, 378 | alignment: text_alignment, 379 | }; 380 | 381 | commands 382 | .spawn_bundle(Text2dBundle { 383 | text: scores_text, 384 | transform: Transform::from_xyz(-300.0, 200.0, 0.0), 385 | ..default() 386 | }) 387 | .insert(Renderable); 388 | 389 | let spawner = Spawner::new(*size_x, *size_y); 390 | 391 | // grid 392 | for x in 0..*size_x { 393 | for y in 0..*size_y { 394 | spawner.spawn(&mut commands, Position(x, y), SpawnType::Grid); 395 | } 396 | } 397 | 398 | for block in blocks { 399 | spawner.spawn(&mut commands, *block, SpawnType::Block); 400 | } 401 | 402 | for explosion in explosions { 403 | spawner.spawn(&mut commands, *explosion, SpawnType::Explosion); 404 | } 405 | 406 | for bomb in bombs { 407 | spawner.spawn(&mut commands, bomb.position, SpawnType::Bomb); 408 | // TODO spawn time left 409 | } 410 | 411 | players.iter().for_each(|(_, _, _, position, color)| { 412 | spawner.spawn(&mut commands, *position, SpawnType::Player(*color)); 413 | }); 414 | } 415 | } 416 | } 417 | } 418 | -------------------------------------------------------------------------------- /src/serialize/deserializer.rs: -------------------------------------------------------------------------------- 1 | use std::io::{Cursor, Read}; 2 | 3 | use crate::serialize::DeserError; 4 | use byteorder::{NetworkEndian, ReadBytesExt}; 5 | use serde::de::{ 6 | self, DeserializeOwned, DeserializeSeed, EnumAccess, MapAccess, SeqAccess, VariantAccess, 7 | Visitor, 8 | }; 9 | use serde::Deserialize; 10 | 11 | use super::error::Result; 12 | 13 | pub struct Deserializer { 14 | input: R, 15 | } 16 | 17 | impl Deserializer { 18 | pub fn new(input: R) -> Self { 19 | Deserializer { input } 20 | } 21 | 22 | pub fn deserialize(&mut self) -> Result { 23 | T::deserialize(self) 24 | } 25 | } 26 | 27 | impl<'de> Deserializer> { 28 | pub fn from_bytes(input: &'de [u8]) -> Self { 29 | Deserializer { 30 | input: Cursor::new(input), 31 | } 32 | } 33 | } 34 | 35 | pub fn from_bytes<'de, T>(input: &'de [u8]) -> Result 36 | where 37 | T: Deserialize<'de>, 38 | { 39 | let mut deserializer = Deserializer::from_bytes(input); 40 | let value = T::deserialize(&mut deserializer)?; 41 | 42 | if deserializer.input.position() == deserializer.input.get_ref().len() as u64 { 43 | Ok(value) 44 | } else { 45 | Err(DeserError::TrailingData) 46 | } 47 | } 48 | 49 | impl<'de, 'a, R: Read> de::Deserializer<'de> for &'a mut Deserializer { 50 | type Error = DeserError; 51 | 52 | fn deserialize_any(self, _visitor: V) -> Result 53 | where 54 | V: Visitor<'de>, 55 | { 56 | unimplemented!() 57 | } 58 | 59 | fn deserialize_bool(self, visitor: V) -> Result 60 | where 61 | V: Visitor<'de>, 62 | { 63 | let byte = self.input.read_i8()?; 64 | match byte { 65 | 0 => visitor.visit_bool(false), 66 | 1 => visitor.visit_bool(true), 67 | _ => Err(DeserError::InvalidBool), 68 | } 69 | } 70 | 71 | fn deserialize_i8(self, visitor: V) -> Result 72 | where 73 | V: Visitor<'de>, 74 | { 75 | visitor.visit_i8(self.input.read_i8()?) 76 | } 77 | 78 | fn deserialize_i16(self, visitor: V) -> Result 79 | where 80 | V: Visitor<'de>, 81 | { 82 | visitor.visit_i16(self.input.read_i16::()?) 83 | } 84 | 85 | fn deserialize_i32(self, visitor: V) -> Result 86 | where 87 | V: Visitor<'de>, 88 | { 89 | visitor.visit_i32(self.input.read_i32::()?) 90 | } 91 | 92 | fn deserialize_i64(self, visitor: V) -> Result 93 | where 94 | V: Visitor<'de>, 95 | { 96 | visitor.visit_i64(self.input.read_i64::()?) 97 | } 98 | 99 | fn deserialize_u8(self, visitor: V) -> Result 100 | where 101 | V: Visitor<'de>, 102 | { 103 | visitor.visit_u8(self.input.read_u8()?) 104 | } 105 | 106 | fn deserialize_u16(self, visitor: V) -> Result 107 | where 108 | V: Visitor<'de>, 109 | { 110 | visitor.visit_u16(self.input.read_u16::()?) 111 | } 112 | 113 | fn deserialize_u32(self, visitor: V) -> Result 114 | where 115 | V: Visitor<'de>, 116 | { 117 | visitor.visit_u32(self.input.read_u32::()?) 118 | } 119 | 120 | fn deserialize_u64(self, visitor: V) -> Result 121 | where 122 | V: Visitor<'de>, 123 | { 124 | visitor.visit_u64(self.input.read_u64::()?) 125 | } 126 | 127 | fn deserialize_f32(self, _visitor: V) -> Result 128 | where 129 | V: Visitor<'de>, 130 | { 131 | unimplemented!() 132 | } 133 | 134 | fn deserialize_f64(self, _visitor: V) -> Result 135 | where 136 | V: Visitor<'de>, 137 | { 138 | unimplemented!() 139 | } 140 | 141 | fn deserialize_char(self, _visitor: V) -> Result 142 | where 143 | V: Visitor<'de>, 144 | { 145 | unimplemented!() 146 | } 147 | 148 | fn deserialize_str(self, visitor: V) -> Result 149 | where 150 | V: Visitor<'de>, 151 | { 152 | // TODO: this can be improved in terms of borrowing 153 | let length = self.input.read_u8()?; 154 | let mut buf = vec![0; length as usize]; 155 | self.input.read_exact(&mut buf)?; 156 | visitor.visit_str(std::str::from_utf8(&buf)?) 157 | } 158 | 159 | fn deserialize_string(self, visitor: V) -> Result 160 | where 161 | V: Visitor<'de>, 162 | { 163 | self.deserialize_str(visitor) 164 | } 165 | 166 | fn deserialize_bytes(self, _visitor: V) -> Result 167 | where 168 | V: Visitor<'de>, 169 | { 170 | unimplemented!() 171 | } 172 | 173 | fn deserialize_byte_buf(self, _visitor: V) -> Result 174 | where 175 | V: Visitor<'de>, 176 | { 177 | unimplemented!() 178 | } 179 | 180 | fn deserialize_option(self, visitor: V) -> Result 181 | where 182 | V: Visitor<'de>, 183 | { 184 | let byte = self.input.read_u8()?; 185 | match byte { 186 | 0 => visitor.visit_none(), 187 | 1 => visitor.visit_some(self), 188 | _ => Err(DeserError::InvalidOption), 189 | } 190 | } 191 | 192 | fn deserialize_unit(self, visitor: V) -> Result 193 | where 194 | V: Visitor<'de>, 195 | { 196 | let byte = self.input.read_u8()?; 197 | match byte { 198 | 0 => visitor.visit_unit(), 199 | _ => Err(DeserError::InvalidUnit), 200 | } 201 | } 202 | 203 | fn deserialize_unit_struct(self, _name: &'static str, visitor: V) -> Result 204 | where 205 | V: Visitor<'de>, 206 | { 207 | self.deserialize_unit(visitor) 208 | } 209 | 210 | fn deserialize_newtype_struct(self, _name: &'static str, visitor: V) -> Result 211 | where 212 | V: Visitor<'de>, 213 | { 214 | visitor.visit_newtype_struct(self) 215 | } 216 | 217 | fn deserialize_seq(self, visitor: V) -> Result 218 | where 219 | V: Visitor<'de>, 220 | { 221 | let length = self.input.read_u32::()?; 222 | visitor.visit_seq(Counted::new(self, length as usize)) 223 | } 224 | 225 | fn deserialize_tuple(self, len: usize, visitor: V) -> Result 226 | where 227 | V: Visitor<'de>, 228 | { 229 | visitor.visit_seq(Counted::new(self, len)) 230 | } 231 | 232 | fn deserialize_tuple_struct( 233 | self, 234 | _name: &'static str, 235 | len: usize, 236 | visitor: V, 237 | ) -> Result 238 | where 239 | V: Visitor<'de>, 240 | { 241 | self.deserialize_tuple(len, visitor) 242 | } 243 | 244 | fn deserialize_map(self, visitor: V) -> Result 245 | where 246 | V: Visitor<'de>, 247 | { 248 | let length = self.input.read_u32::()?; 249 | visitor.visit_map(Counted::new(self, length as usize)) 250 | } 251 | 252 | fn deserialize_struct( 253 | self, 254 | _name: &'static str, 255 | fields: &'static [&'static str], 256 | visitor: V, 257 | ) -> Result 258 | where 259 | V: Visitor<'de>, 260 | { 261 | let len = fields.len(); 262 | visitor.visit_seq(Counted::new(self, len)) 263 | } 264 | 265 | fn deserialize_enum( 266 | self, 267 | _name: &'static str, 268 | _variants: &'static [&'static str], 269 | visitor: V, 270 | ) -> Result 271 | where 272 | V: Visitor<'de>, 273 | { 274 | visitor.visit_enum(Variant::new(self)) 275 | } 276 | 277 | fn deserialize_identifier(self, visitor: V) -> Result 278 | where 279 | V: Visitor<'de>, 280 | { 281 | self.deserialize_u8(visitor) 282 | } 283 | 284 | fn deserialize_ignored_any(self, visitor: V) -> Result 285 | where 286 | V: Visitor<'de>, 287 | { 288 | self.deserialize_any(visitor) 289 | } 290 | } 291 | 292 | struct Variant<'a, R: Read> { 293 | de: &'a mut Deserializer, 294 | } 295 | 296 | impl<'a, R: Read> Variant<'a, R> { 297 | fn new(de: &'a mut Deserializer) -> Self { 298 | Variant { de } 299 | } 300 | } 301 | 302 | impl<'de, 'a, R: Read> EnumAccess<'de> for Variant<'a, R> { 303 | type Error = DeserError; 304 | type Variant = Self; 305 | 306 | fn variant_seed(self, seed: V) -> Result<(V::Value, Self::Variant)> 307 | where 308 | V: DeserializeSeed<'de>, 309 | { 310 | let val = seed.deserialize(&mut *self.de)?; 311 | Ok((val, self)) 312 | } 313 | } 314 | 315 | impl<'de, 'a, R: Read> VariantAccess<'de> for Variant<'a, R> { 316 | type Error = DeserError; 317 | 318 | fn unit_variant(self) -> Result<()> { 319 | Ok(()) 320 | } 321 | 322 | fn newtype_variant_seed(self, seed: T) -> Result 323 | where 324 | T: DeserializeSeed<'de>, 325 | { 326 | seed.deserialize(self.de) 327 | } 328 | 329 | fn tuple_variant(self, len: usize, visitor: V) -> Result 330 | where 331 | V: Visitor<'de>, 332 | { 333 | de::Deserializer::deserialize_tuple(self.de, len, visitor) 334 | } 335 | 336 | fn struct_variant(self, fields: &'static [&'static str], visitor: V) -> Result 337 | where 338 | V: Visitor<'de>, 339 | { 340 | de::Deserializer::deserialize_struct(self.de, "", fields, visitor) 341 | } 342 | } 343 | 344 | struct Counted<'a, R: Read> { 345 | de: &'a mut Deserializer, 346 | index: usize, 347 | length: usize, 348 | } 349 | 350 | impl<'a, R: Read> Counted<'a, R> { 351 | fn new(de: &'a mut Deserializer, length: usize) -> Self { 352 | Counted { 353 | de, 354 | index: 0, 355 | length, 356 | } 357 | } 358 | } 359 | 360 | impl<'de, 'a, R: Read> SeqAccess<'de> for Counted<'a, R> { 361 | type Error = DeserError; 362 | 363 | fn next_element_seed(&mut self, seed: T) -> Result> 364 | where 365 | T: DeserializeSeed<'de>, 366 | { 367 | // Check if there are no more elements. 368 | if self.index == self.length { 369 | return Ok(None); 370 | } 371 | // Deserialize an array element. 372 | let element = seed.deserialize(&mut *self.de).map(Some); 373 | self.index += 1; 374 | element 375 | } 376 | } 377 | 378 | impl<'de, 'a, R: Read> MapAccess<'de> for Counted<'a, R> { 379 | type Error = DeserError; 380 | 381 | fn next_key_seed(&mut self, seed: K) -> Result> 382 | where 383 | K: DeserializeSeed<'de>, 384 | { 385 | // Check if there are no more entries. 386 | if self.index == self.length { 387 | return Ok(None); 388 | } 389 | // Deserialize a map key. 390 | seed.deserialize(&mut *self.de).map(Some) 391 | } 392 | 393 | fn next_value_seed(&mut self, seed: V) -> Result 394 | where 395 | V: DeserializeSeed<'de>, 396 | { 397 | let value = seed.deserialize(&mut *self.de); 398 | self.index += 1; 399 | value 400 | } 401 | } 402 | 403 | #[cfg(test)] 404 | mod test { 405 | use super::*; 406 | 407 | #[test] 408 | fn test_deserialize_bool() { 409 | let buf = vec![0x01]; 410 | let result: bool = from_bytes(&buf).unwrap(); 411 | assert!(result); 412 | 413 | let buf = vec![0x00]; 414 | let result: bool = from_bytes(&buf).unwrap(); 415 | assert!(!result); 416 | 417 | let buf = vec![0x02]; 418 | let result = from_bytes::(&buf); 419 | assert!(result.is_err()); 420 | } 421 | 422 | #[test] 423 | fn test_deserialize_u32() { 424 | let buf = vec![0x12, 0x34, 0x56, 0x78]; 425 | let result: u32 = from_bytes(&buf).unwrap(); 426 | assert_eq!(result, 0x12345678); 427 | } 428 | 429 | #[test] 430 | fn test_deserialize_string() { 431 | let buf = vec![3, b'a', b'b', b'c']; 432 | let result: String = from_bytes(&buf).unwrap(); 433 | assert_eq!(result, "abc"); 434 | } 435 | 436 | #[test] 437 | fn test_deserialize_struct() { 438 | #[derive(Deserialize, PartialEq, Eq, Debug)] 439 | struct Message { 440 | message: String, 441 | } 442 | 443 | let message = Message { 444 | message: "hello".to_string(), 445 | }; 446 | let buf = [5, b'h', b'e', b'l', b'l', b'o']; 447 | let result: Message = from_bytes(&buf).unwrap(); 448 | assert_eq!(result, message); 449 | } 450 | 451 | #[test] 452 | fn deserialize_struct_tuple() { 453 | #[derive(Deserialize, PartialEq, Eq, Debug)] 454 | struct Message(String, u32); 455 | let message = Message("hello".to_string(), 0x12345678); 456 | let buf = [5, b'h', b'e', b'l', b'l', b'o', 0x12, 0x34, 0x56, 0x78]; 457 | let result: Message = from_bytes(&buf).unwrap(); 458 | assert_eq!(result, message); 459 | } 460 | 461 | #[test] 462 | fn test_deserialize_enum() { 463 | #[derive(Deserialize, PartialEq, Eq, Debug)] 464 | enum Message { 465 | Hello(String), 466 | Goodbye(String), 467 | } 468 | 469 | let buf = vec![0, 5, b'w', b'o', b'r', b'l', b'd']; 470 | 471 | let message = Message::Hello("world".to_string()); 472 | let result: Message = from_bytes(&buf).unwrap(); 473 | assert_eq!(result, message); 474 | 475 | let message = Message::Goodbye("worlds".to_string()); 476 | let buf = [1, 6, b'w', b'o', b'r', b'l', b'd', b's']; 477 | let result: Message = from_bytes(&buf).unwrap(); 478 | assert_eq!(result, message); 479 | } 480 | 481 | #[test] 482 | fn test_deserialize_nested_enum() { 483 | #[derive(Deserialize, Debug, Eq, PartialEq)] 484 | enum Message { 485 | Hello, 486 | Goodbye, 487 | } 488 | 489 | #[derive(Deserialize, Debug, Eq, PartialEq)] 490 | enum NestedMessage { 491 | Variant1(Message), 492 | Variant2 { message: Message, num: u16 }, 493 | } 494 | 495 | let message = NestedMessage::Variant1(Message::Hello); 496 | let buf = [0, 0]; 497 | let result: NestedMessage = from_bytes(&buf).unwrap(); 498 | assert_eq!(result, message); 499 | 500 | let message = NestedMessage::Variant1(Message::Goodbye); 501 | let buf = [0, 1]; 502 | let result: NestedMessage = from_bytes(&buf).unwrap(); 503 | assert_eq!(result, message); 504 | 505 | let message = NestedMessage::Variant2 { 506 | message: Message::Hello, 507 | num: 0x1234, 508 | }; 509 | let buf = [1, 0, 0x12, 0x34]; 510 | let result: NestedMessage = from_bytes(&buf).unwrap(); 511 | assert_eq!(result, message); 512 | } 513 | 514 | #[test] 515 | fn test_deserialize_vec() { 516 | #[derive(Deserialize, Debug, Eq, PartialEq)] 517 | enum Message { 518 | Hello(String), 519 | Goodbye, 520 | } 521 | let vec = vec![ 522 | Message::Hello("world".to_string()), 523 | Message::Goodbye, 524 | Message::Hello("something".to_string()), 525 | ]; 526 | let buf = [ 527 | 0, 0, 0, 3, 0, 5, b'w', b'o', b'r', b'l', b'd', 1, 0, 9, b's', b'o', b'm', b'e', b't', 528 | b'h', b'i', b'n', b'g', 529 | ]; 530 | let result: Vec = from_bytes(&buf).unwrap(); 531 | assert_eq!(result, vec); 532 | } 533 | 534 | #[test] 535 | fn test_serialize_map() { 536 | #[derive(Deserialize, Debug, Eq, PartialEq)] 537 | enum Message { 538 | Hello(String), 539 | Goodbye, 540 | } 541 | let map = vec![ 542 | ("hello".to_string(), Message::Hello("world".to_string())), 543 | ("goodbye".to_string(), Message::Goodbye), 544 | ]; 545 | let buf = [ 546 | 0, 0, 0, 2, 5, b'h', b'e', b'l', b'l', b'o', 0, 5, b'w', b'o', b'r', b'l', b'd', 7, 547 | b'g', b'o', b'o', b'd', b'b', b'y', b'e', 1, 548 | ]; 549 | let result: Vec<(String, Message)> = from_bytes(&buf).unwrap(); 550 | assert_eq!(result, map); 551 | } 552 | } 553 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Bombowe roboty 2 | 3 | Pytania proszę wysyłać na adres agluszak@mimuw.edu.pl. 4 | 5 | Historia zmian: 6 | - **10.06.2022** - doprecyzowanie jak przebiega generacja początkowych bloków 7 | - **08.06.2022** - doprecyzowanie jak wygląda koniec gry, dodanie skryptu `verifier.sh` 8 | - **06.06.2022** - nowe pytania 9 | - **25.05.2023** - Doprecyzowanie, kiedy wysyłane są komunikaty do GUI: 10 | Po Turn - Game 11 | Po AcceptedPlayer, GameEnded i Hello - Lobby 12 | Po GameStarted - nic 13 | 14 | A wszystkie pozycje początkowe graczy i bloków są wysyłane w turze 0. 15 | - **24.05.2022** - Wycofanie poniższego (nie będziemy osobno oceniać jakości kodu po pierwszej części) 16 | - **23.05.2022** - Przy oddawaniu klienta pliki (lub ich części) dotyczące serwera zostaną uznane za zbędne 17 | - **20.05.2022** - WAŻNE: zmiana jak wysyłane są informacje o rozgrywce po dołączeniu w trakcie. Doprecyzowanie, w jaki sposób obliczany jest wybuch bomby. 18 | - **18.05.2022** - nowe pytania 19 | - **16.05.2022** - obsługa IPv6 w GUI, doprecyzowanie jak projekt ma się budować 20 | - **13.05.2022** - zmiana display na gui, dodanie pytań 21 | - **10.05.2022** - doprecyzowanie jak identyfikowani są klienci 22 | - **09.05.2022** - poprawki w GUI, nowe pytania w FAQ 23 | - **08.05.2022** - doprecyzowanie jak obliczać wybuch kilku bomb, zmiana generatora liczb losowych, zmiana flag kompilatora 24 | 25 | ## 0. Dostarczone programy 26 | 27 | Do uruchomienia programów potrzeba [kompilatora Rusta](https://rustup.rs/), a także pewnych [bibliotek systemowych](https://github.com/bevyengine/bevy/blob/main/docs/linux_dependencies.md). 28 | 29 | Po zainstalowaniu kompilatora należy wykonać komendę: 30 | `cargo run --bin ` i uzupełnić parametry. 31 | 32 | Skompilowany serwer (bynajmniej nie wzorcowy) jest dostępny [tutaj](https://students.mimuw.edu.pl/~agluszak/server). Został on skompilowany na maszynie `students`. Aby wyświetlały się komunikaty, należy uruchomić go ze zmienną środowiskową `RUST_LOG=debug`. 33 | 34 | ### 0.1. GUI 35 | 36 | Interfejs graficzny dla gry Bombowe Roboty. 37 | GUI prawdopodobnie będzie jeszcze aktualizowane. 38 | 39 | #### Sterowanie 40 | 41 | ``` 42 | W, strzałka w górę - porusza robotem w górę. 43 | S, strzałka w dół - porusza robotem w dół. 44 | A, strzałka w lewo - porusza robotem w lewo. 45 | D, strzałka w prawo - porusza robotem w prawo. 46 | Spacja, J, Z - kładzie bombę. 47 | K, X - blokuje pole. 48 | ``` 49 | 50 | ### 0.2. Weryfikator 51 | 52 | Ten program pozwala sprawdzić, czy wiadomości są poprawnie serializowane. 53 | Innymi słowy, jest to wzorcowy deserializator. Można łączyć się z nim zarówno po TCP, jak i UDP (z parametrem `-u`). 54 | Przy uruchamianiu należy podać, jakiego rodzaju wiadomości mają być sprawdzane. 55 | 56 | Przykładowo, jeśli chcemy sprawdzić, czy klient wysyła prawidłowe wiadomości do serwera, wykonać: 57 | `cargo run --bin verifier -- -p -m client` 58 | 59 | ## 1. Gra Bombowe roboty 60 | 61 | ### 1.1. Zasady gry 62 | 63 | Tegoroczne duże zadanie zaliczeniowe polega na napisaniu gry sieciowej - 64 | uproszczonej wersji gry [Bomberman](https://en.wikipedia.org/wiki/Bomberman). 65 | Gra rozgrywa się na prostokątnym ekranie. 66 | Uczestniczy w niej co najmniej jeden gracz. 67 | Każdy z graczy steruje ruchem robota. 68 | Gra rozgrywa się w turach. 69 | Trwa ona przez z góry znaną liczbę tur. 70 | W każdej turze robot może: 71 | 72 | - nic nie zrobić 73 | - przesunąć się na sąsiednie pole (o ile nie jest ono zablokowane) 74 | - położyć pod sobą bombę 75 | - zablokować pole pod sobą 76 | 77 | Gra toczy się cyklicznie - po uzbieraniu się odpowiedniej liczby graczy 78 | rozpoczyna się nowa rozgrywka na tym samym serwerze. 79 | Stan gry przed rozpoczęciem rozgrywki będziemy nazywać `Lobby`. 80 | 81 | ### 1.2. Architektura rozwiązania 82 | 83 | Na grę składają się trzy komponenty: serwer, klient, serwer obsługujący 84 | interfejs użytkownika. 85 | Należy zaimplementować serwer i klienta. 86 | Aplikację implementującą serwer obsługujący graficzny interfejs użytkownika 87 | (ang. *GUI*) dostarczamy. 88 | 89 | Serwer komunikuje się z klientami, zarządza stanem gry, odbiera od klientów 90 | informacje o wykonywanych ruchach oraz rozsyła klientom zmiany stanu gry. 91 | Serwer pamięta wszystkie zdarzenia dla bieżącej partii i przesyła je w razie 92 | potrzeby klientom. 93 | 94 | Klient komunikuje się z serwerem gry oraz interfejsem użytkownika. 95 | 96 | Zarówno klient jak i serwer mogą być wielowątkowe. 97 | 98 | Specyfikacje protokołów komunikacyjnych, rodzaje zdarzeń oraz formaty 99 | komunikatów i poleceń są opisane poniżej. 100 | 101 | ### 1.3. Parametry wywołania programów 102 | 103 | Serwer: 104 | ``` 105 | -b, --bomb-timer 106 | -c, --players-count 107 | -d, --turn-duration 108 | -e, --explosion-radius 109 | -h, --help Wypisuje jak używać programu 110 | -k, --initial-blocks 111 | -l, --game-length 112 | -n, --server-name 113 | -p, --port 114 | -s, --seed 115 | -x, --size-x 116 | -y, --size-y 117 | ``` 118 | 119 | Klient: 120 | ``` 121 | -d, --gui-address <(nazwa hosta):(port) lub (IPv4):(port) lub (IPv6):(port)> 122 | -h, --help Wypisuje jak używać programu 123 | -n, --player-name 124 | -p, --port Port na którym klient nasłuchuje komunikatów od GUI 125 | -s, --server-address <(nazwa hosta):(port) lub (IPv4):(port) lub (IPv6):(port)> 126 | ``` 127 | 128 | Interfejs graficzny: 129 | ``` 130 | -c, --client-address <(nazwa hosta):(port) lub (IPv4):(port) lub (IPv6):(port)> 131 | -h, --help Wypisuje jak używać programu 132 | -p, --port Port na którym GUI nasłuchuje komunikatów od klienta 133 | ``` 134 | 135 | Do parsowania parametrów linii komend można użyć funkcji `getopt` 136 | z [biblioteki standardowej C](https://linux.die.net/man/3/getopt) lub modułu `program_options` 137 | z biblioteki [Boost](https://www.boost.org/doc/libs/1_79_0/doc/html/program_options.html). 138 | 139 | Wystarczy zaimplementować rozpoznawanie krótkich (`-c`, `-x` itd.) parametrów. 140 | 141 | ## 2. Protokół komunikacyjny pomiędzy klientem a serwerem 142 | 143 | Wymiana danych odbywa się po TCP. Przesyłane są dane binarne, zgodne z poniżej zdefiniowanymi 144 | formatami komunikatów. W komunikatach wszystkie liczby przesyłane są w sieciowej kolejności bajtów, 145 | a wszystkie napisy muszą być zakodowane w UTF-8 i mieć długość krótszą niż 256 bajtów. 146 | 147 | Napisy (String) mają następującą reprezentację binarną: 148 | `[1 bajt określający długość napisu w bajtach][bajty bez ostatniego bajtu zerowego]`. 149 | 150 | Listy są serializowane w postaci `[4 bajty długości listy][elementy listy]`. 151 | Mapy są serializowane w postaci `[4 bajty długości mapy][klucz][wartość][klucz][wartość]...`. 152 | 153 | Pola w strukturze serializowane są bezpośrednio po bajcie oznaczającym typ struktury. 154 | 155 | Należy wyłączyć algorytm Nagle'a (tzn. ustawić flagę TCP_NODELAY). 156 | 157 | ### 2.1. Komunikaty od klienta do serwera 158 | 159 | ``` 160 | enum ClientMessage { 161 | [0] Join { name: String }, 162 | [1] PlaceBomb, 163 | [2] PlaceBlock, 164 | [3] Move { direction: Direction }, 165 | } 166 | ``` 167 | 168 | Typ Direction ma następującą reprezentację binarną: 169 | 170 | ``` 171 | enum Direction { 172 | [0] Up, 173 | [1] Right, 174 | [2] Down, 175 | [3] Left, 176 | } 177 | ``` 178 | 179 | Wiadomość od klienta `Join(“Żółć!”)` zostanie zserializowana jako ciąg bajtów 180 | `[0, 9, 197, 187, 195, 179, 197, 130, 196, 135, 33]`, gdzie: 181 | 182 | ``` 183 | 0 - rodzaj wiadomości 184 | 9 - długość napisu 185 | 197, 187 - 'Ż' 186 | 195, 179 - 'ó' 187 | 197, 130 - 'ł' 188 | 196, 135 - 'ć' 189 | 33 - '!' 190 | ``` 191 | 192 | Natomiast wiadomość `Join(“👩🏼‍👩🏼‍👧🏼‍👦🏼🇵🇱”)` zostanie zserializowana jako ciąg bajtów 193 | `[0, 49, 240, 159, 145, 169, 240, 159, 143, 188, 226, 128, 141, 240, 159, 145, 169, 240, 159, 143, 188, 226, 128, 141, 240, 159, 145, 167, 240, 159, 143, 188, 226, 128, 141, 240, 159, 145, 166, 240, 159, 143, 188, 240, 159, 135, 181, 240, 159, 135, 177]`. 194 | 195 | Wiadomość `Move(Down)` zserializowana zostanie jako ciąg bajtów `[3, 2]`. 196 | 197 | 198 | 199 | Klient po podłączeniu się do serwera zaczyna obserwować rozgrywkę, jeżeli ta jest w toku. 200 | W przeciwnym razie może zgłosić chęć wzięcia w niej udziału, wysyłając komunikat `Join`. 201 | 202 | Serwer ignoruje komunikaty `Join` wysłane w trakcie rozgrywki. Serwer ignoruje również komunikaty typu innego niż `Join` w `Lobby`. 203 | 204 | 205 | ### 2.2. Komunikaty od serwera do klienta 206 | 207 | ``` 208 | enum ServerMessage { 209 | [0] Hello { 210 | server_name: String, 211 | players_count: u8, 212 | size_x: u16, 213 | size_y: u16, 214 | game_length: u16, 215 | explosion_radius: u16, 216 | bomb_timer: u16, 217 | }, 218 | [1] AcceptedPlayer { 219 | id: PlayerId, 220 | player: Player, 221 | }, 222 | [2] GameStarted { 223 | players: Map, 224 | }, 225 | [3] Turn { 226 | turn: u16, 227 | events: List, 228 | }, 229 | [4] GameEnded { 230 | scores: Map, 231 | }, 232 | } 233 | ``` 234 | 235 | 236 | Wiadomość od serwera typu `Turn` 237 | 238 | ``` 239 | ServerMessage::Turn { 240 | turn: 44, 241 | events: [ 242 | Event::PlayerMoved { 243 | id: PlayerId(3), 244 | position: Position(2, 4), 245 | }, 246 | Event::PlayerMoved { 247 | id: PlayerId(4), 248 | position: Position(3, 5), 249 | }, 250 | Event::BombPlaced { 251 | id: BombId(5), 252 | position: Position(5, 7), 253 | }, 254 | ], 255 | ``` 256 | 257 | będzie miała następującą reprezentację binarną: 258 | 259 | ``` 260 | [3, 0, 44, 0, 0, 0, 3, 2, 3, 0, 2, 0, 4, 2, 4, 0, 3, 0, 5, 0, 0, 0, 0, 5, 0, 5, 0, 7] 261 | 262 | 3 - rodzaj wiadomości od serwera (`Turn`) 263 | 0, 44 - numer tury 264 | 0, 0, 0, 3 - liczba zdarzeń 265 | 2 - rodzaj zdarzenia (`PlayerMoved`) 266 | 3 - id gracza 267 | 0, 2 - współrzędna x 268 | 0, 4 - współrzędna y 269 | 2 - rodzaj zdarzenia (`PlayerMoved`) 270 | 4 - id gracza 271 | 0, 3 - współrzędna x 272 | 0, 5 - współrzędna y 273 | 0 - rodzaj zdarzenia (`BombPlaced`) 274 | 0, 0, 0, 5 - id bomby 275 | 0, 5 - współrzędna x 276 | 0, 7 - współrzędna y 277 | ``` 278 | 279 | Dostarczymy program do weryfikowania poprawności danych. 280 | 281 | ### 2.3. Definicje użytych powyżej rekordów 282 | 283 | Event: 284 | [0] BombPlaced { id: BombId, position: Position }, 285 | [1] BombExploded { id: BombId, robots_destroyed: List, blocks_destroyed: List }, 286 | [2] PlayerMoved { id: PlayerId, position: Position }, 287 | [3] BlockPlaced { position: Position }, 288 | 289 | BombId: u32 290 | Bomb: { position: Position, timer: u16 }, 291 | PlayerId: u8 292 | Position: { x: u16, y: u16 } 293 | Player: { name: String, address: String } 294 | Score: u32 295 | 296 | Pole `address` w strukturze `Player` może reprezentować zarówno adres IPv4, jak i adres IPv6. 297 | 298 | Liczba typu `Score` informuje o tym, ile razy robot danego gracza został zniszczony. 299 | 300 | 301 | ### 2.4. Generator liczb losowych 302 | 303 | Do wytwarzania wartości losowych należy użyć poniższego deterministycznego 304 | generatora liczb 32-bitowych. Kolejne wartości zwracane przez ten generator 305 | wyrażone są wzorem: 306 | 307 | r_0 = (seed * 48271) mod 2147483647 308 | r_i = (r_{i-1} * 48271) mod 2147483647 309 | 310 | 311 | gdzie wartość `seed` jest 32-bitowa i jest przekazywana do serwera za pomocą 312 | parametru `-s`. Jeśli ten parametr nie jest zdefiniowany, można jako wartości 313 | domyślnej użyć dowolnej liczby, która będzie zmieniać się przy każdym uruchomieniu, np. 314 | `unsigned seed = time(NULL)` (C) 315 | lub `unsigned seed = std::chrono::system_clock::now().time_since_epoch().count()` (C++). 316 | 317 | Powyższy generator odpowiada generatorowi `std::minstd_rand`. 318 | 319 | Należy użyć dokładnie takiego generatora, żeby umożliwić automatyczne testowanie 320 | rozwiązania (uwaga na konieczność wykonywania pośrednich obliczeń na typie 321 | 64-bitowym). 322 | 323 | Przykłady użycia generatora zostały podane w plikach `c/random.c` oraz `cpp/random.cpp`. 324 | 325 | ### 2.5. Stan gry 326 | 327 | Serwer jest „zarządcą” stanu gry, do klientów przesyła informacje o zdarzeniach. Klienci je agregują 328 | i przesyłają zagregowany stan do interfejsu użytkownika. Interfejs nie przechowuje w ogóle żadnego stanu. 329 | 330 | Serwer powinien przechowywać następujące informacje: 331 | 332 | - lista graczy (nazwa, adres IP, numer portu) 333 | - stan generatora liczb losowych (innymi słowy stan generatora NIE restartuje się po każdej rozgrywce) 334 | 335 | Oraz tylko w przypadku toczącej się rozgrywki: 336 | 337 | - numer tury 338 | - lista wszystkich tur od początku rozgrywki 339 | - pozycje graczy 340 | - liczba śmierci każdego gracza 341 | - informacje o istniejących bombach (pozycja, czas) 342 | - pozycje istniejących bloków 343 | 344 | Lewy dolny róg planszy ma współrzędne `(0, 0)`, odcięte rosną w prawo, 345 | a rzędne w górę. 346 | 347 | Klient powinien przechowywać zagregowany stan tak, aby móc wysyłać komunikaty do GUI. W szczególności klient powinien pamiętać, ile razy dany robot został zniszczony (aby móc wysłać tę informację w polu `scores`). 348 | 349 | ### 2.6. Podłączanie i odłączanie klientów 350 | 351 | Klient wysyła komunikat `Join` do serwera po otrzymaniu dowolnego (poprawnego) komunikatu od GUI, o ile klient jest w stanie `Lobby` (tzn. nie otrzymał od serwera komunikatu `GameStarted`). 352 | 353 | Po podłączeniu klienta do serwera serwer wysyła do niego komunikat `Hello`. 354 | Jeśli rozgrywka jeszcze nie została rozpoczęta, 355 | serwer wysyła komunikaty `AcceptedPlayer` z informacją o podłączonych graczach. 356 | Jeśli rozgrywka już została rozpoczęta, serwer wysyła komunikat `GameStarted` z informacją o rozpoczęciu rozgrywki, 357 | a następnie wysyła wszystkie dotychczasowe komunikaty `Turn`. 358 | 359 | Jeśli rozgrywka nie jest jeszcze rozpoczęta, to wysłanie przez klienta komunikatu `Join` 360 | powoduje dodanie go do listy graczy. Serwer następnie rozsyła do wszystkich klientów komunikat `AcceptedPlayer`. 361 | 362 | Graczom nadawane jest ID w kolejności podłączenia (tzn. odebrania komunikatu `Join` przez serwer). 363 | Dwoje graczy może mieć taką samą nazwę. 364 | Ponieważ klienci łączą się z serwerem po TCP, wiadomo który komunikat przychodzi od którego klienta. 365 | 366 | Odłączenie gracza w trakcie rozgrywki powoduje tylko tyle, że jego robot przestaje się ruszać. 367 | Odłączenie klienta-gracza przed rozpoczęciem rozgrywki nie powoduje skreślenia go z listy graczy. 368 | Odłączenie klienta-obserwatora nie wpływa na działanie serwera. 369 | 370 | ### 2.7. Rozpoczęcie partii i zarządzanie podłączonymi klientami 371 | 372 | Partia rozpoczyna się, gdy odpowiednio wielu graczy się zgłosi. Musi być dokładnie tylu graczy, ile 373 | jest wyspecyfikowane przy uruchomieniu serwera. 374 | 375 | Inicjacja stanu gry przebiega następująco: 376 | 377 | ``` 378 | nr_tury = 0 379 | zdarzenia = [] 380 | 381 | dla każdego gracza w kolejności id: 382 | pozycja_x_robota = random() % szerokość_planszy 383 | pozycja_y_robota = random() % wysokość_planszy 384 | 385 | dodaj zdarzenie `PlayerMoved` do listy 386 | 387 | tyle razy ile wynosi parametr `initial_blocks`: 388 | pozycja_x_bloku = random() % szerokość_planszy 389 | pozycja_y_bloku = random() % wysokość_planszy 390 | 391 | jeśli nie ma bloku o pozycji (pozycja_x_bloku, pozycja_y_bloku) na liście: 392 | dodaj zdarzenie BlockPlaced do listy 393 | 394 | wyślij komunikat `Turn` 395 | ``` 396 | 397 | ### 2.8. Przebieg partii 398 | 399 | Zasady: 400 | 401 | - Nie ma ograniczenia na liczbę bloków i bomb. 402 | - Gracze nie mogą wchodzić na pole, które jest zablokowane. Mogą natomiast z niego zejść, jeśli znajdą się na nim, 403 | wskutek zablokowania go lub „odrodzenia" się na nim. 404 | - Gracze nie mogą wychodzić poza planszę. 405 | - Wielu graczy może zajmować to samo pole. 406 | - Bomby mogą zajmować to samo pole. 407 | - Gracze mogą położyć bombę, nawet jeśli stoją na zablokowanym polu (czyli na jednym polu może być blok, wielu graczy i wiele bomb) 408 | - Na danym polu może być maksymalnie jeden blok 409 | 410 | ``` 411 | zdarzenia = [] 412 | 413 | dla każdej bomby: 414 | zmniejsz jej licznik czasu o 1 415 | jeśli licznik wynosi 0: 416 | zaznacz, które bloki znikną w wyniku eksplozji 417 | zaznacz, które roboty zostaną zniszczone w wyniku eksplozji 418 | dodaj zdarzenie `BombExploded` do listy 419 | usuń bombę 420 | 421 | dla każdego gracza w kolejności id: 422 | jeśli robot nie został zniszczony: 423 | jeśli gracz wykonał ruch: 424 | obsłuż ruch gracza i dodaj odpowiednie zdarzenie do listy 425 | jeśli robot został zniszczony: 426 | pozycja_x_robota = random() % szerokość_planszy 427 | pozycja_y_robota = random() % wysokość_planszy 428 | 429 | dodaj zdarzenie `PlayerMoved` do listy 430 | 431 | zwiększ nr_tury o 1 432 | ``` 433 | 434 | W wyniku eksplozji bomby zostają zniszczone wszystkie roboty w jej zasięgu oraz jedynie najbliższe bloki w jej zasięgu. Eksplozja bomby ma kształt krzyża o długości ramienia równej parametrowi `explosion_radius`. Jeśli robot stoi na bloku, który zostanie zniszczony w wyniku eksplozji, to taki robot również jest niszczony. 435 | 436 | Intuicyjnie oznacza to, że można się schować za blokiem, ale położenie bloku pod sobą nie chroni przed eksplozją. 437 | 438 | Przykłady: 439 | ``` 440 | @ - blok 441 | A, B, C... - bomby 442 | 1, 2, 3... - gracze 443 | x - eksplozja 444 | ``` 445 | 446 | ``` 447 | .@2.. 448 | ..1.. 449 | @@A.@ 450 | ..@.. 451 | ..... 452 | ``` 453 | 454 | Pola oznaczone jako eksplozja po wybuchu A z promieniem równym 2: 455 | ``` 456 | .@x.. 457 | ..x.. 458 | @xxxx 459 | ..x.. 460 | ..... 461 | ``` 462 | 463 | A zatem zniszczone zostaną 3 bloki i oba roboty. 464 | 465 | Jeśli na polu jest bomba, blok i jacyś gracze, to wybuch bomby zniszczy blok i wszystkich graczy na tym polu stojących. 466 | 467 | ``` 468 | @@@@@ 469 | @@AB@ 470 | .@@@@ 471 | ``` 472 | 473 | Jednoczesna eksplozja A i B z promieniem równym 2: 474 | ``` 475 | @@xx@ 476 | @xxxx 477 | .@xx@ 478 | ``` 479 | 480 | Po eksplozji: 481 | ``` 482 | @@..@ 483 | @.... 484 | .@..@ 485 | ``` 486 | 487 | Eksplozja jednej bomby nie powoduje eksplozji bomb sąsiednich. 488 | Jeśli kilka bomb wybucha w jednej turze, to skutki eksplozji są sumą teoriomnogościową 489 | pojedynczych eksplozji rozpatrywanych osobno. 490 | W powyższym przykładzie widać że blok o współrzędnych (0, 1) nie został zniszczony. 491 | 492 | ### 2.9. Wykonywanie ruchu 493 | 494 | Serwer przyjmuje informacje o ruchach graczy w następujący sposób: 495 | przez `turn_duration` milisekund oczekuje na informacje od graczy. 496 | Jeśli gracz w tym czasie nie wyśle odpowiedniej wiadomości, 497 | to w danej turze jego robot nic nie robi. 498 | Jeśli w tym czasie gracz wyśle więcej niż jedną wiadomość, 499 | to pod uwagę brana jest tylko ostatnia. 500 | 501 | To serwer decyduje o tym, czy dany ruch jest dozwolony czy nie. Jeśli gracz stojący na krawędzi planszy wyśle komunikat, który spowodowałby wyjście robota poza planszę, to serwer komunikat ignoruje. Podobnie jeśli spróbuje wejść na zablokowane pole. 502 | 503 | ### 2.10. Kończenie rozgrywki 504 | 505 | Po `game_length` turach serwer wysyła do wszystkich klientów wiadomość `GameEnded` i wraca do stanu `Lobby`. Klienci, którzy byli do tej pory graczami, przestają nimi być, ale oczywiście mogą się z powrotem zgłosić przy pomocy komunikatu `Join`. Wszystkie komunikaty otrzymane w czasie ostatniej tury rozgrywki są ignorowane. 506 | 507 | ### 2.11. Błędy w komunikacji 508 | 509 | Co jeśli klient prześle komunikat o nieprawidłowym formacie? Czy należy wtedy uznać go za odłączonego? Tak, bo ponieważ protokół jest binarny i po napotkaniu jakichkolwiek nieprawidłowych danych nie da się dowiedzieć, od którego momentu dane z powrotem są prawidłowe, jedyne co można zrobić to odłączyć klienta. 510 | 511 | 512 | ## 3. Protokół komunikacyjny pomiędzy klientem a interfejsem użytkownika 513 | 514 | Komunikacja z interfejsem odbywa się po UDP przy użyciu komunikatów serializowanych tak jak wyżej. 515 | 516 | Klient wysyła do interfejsu graficznego następujące komunikaty: 517 | 518 | ``` 519 | enum DrawMessage { 520 | [0] Lobby { 521 | server_name: String, 522 | players_count: u8, 523 | size_x: u16, 524 | size_y: u16, 525 | game_length: u16, 526 | explosion_radius: u16, 527 | bomb_timer: u16, 528 | players: Map 529 | }, 530 | [1] Game { 531 | server_name: String, 532 | size_x: u16, 533 | size_y: u16, 534 | game_length: u16, 535 | turn: u16, 536 | players: Map, 537 | player_positions: Map, 538 | blocks: List, 539 | bombs: List, 540 | explosions: List, 541 | scores: Map, 542 | }, 543 | } 544 | ``` 545 | 546 | Explosions w komunikacie `Game` to lista pozycji, na których robot by zginął, gdyby tam stał. 547 | 548 | Klient powinien wysłać taki komunikat po każdej zmianie stanu (tzn. otrzymaniu wiadomości `Turn` jeśli rozgrywka jest w 549 | toku lub `AcceptedPlayer` jeśli rozgrywka się nie toczy). 550 | 551 | Interfejs wysyła do klienta następujące komunikaty: 552 | 553 | ``` 554 | enum InputMessage { 555 | [0] PlaceBomb, 556 | [1] PlaceBlock, 557 | [2] Move { direction: Direction }, 558 | } 559 | ``` 560 | 561 | Są one wysyłane za każdym razem, gdy gracz naciśnie odpowiedni przycisk. 562 | 563 | Można założyć, że komunikaty zmieszczą się w jednym datagramie UDP. Każdy komunikat wysyłany jest w osobnym datagramie. 564 | 565 | ## 4. Ustalenia dodatkowe 566 | 567 | Program klienta w przypadku błędu połączenia z serwerem gry lub interfejsem 568 | użytkownika powinien się zakończyć z kodem wyjścia 1, uprzednio wypisawszy 569 | zrozumiały komunikat na standardowe wyjście błędów. 570 | 571 | Program serwera powinien być odporny na sytuacje błędne, które dają szansę na 572 | kontynuowanie działania. Intencja jest taka, że serwer powinien móc być 573 | uruchomiony na stałe bez konieczności jego restartowania, np. w przypadku 574 | kłopotów komunikacyjnych, czasowej niedostępności sieci, zwykłych zmian jej 575 | konfiguracji itp. 576 | 577 | Serwer nie musi obsługiwać więcej niż 25 podłączonych klientów (graczy + obserwatorów) jednocześnie. 578 | 579 | Programy powinny umożliwiać komunikację zarówno przy użyciu IPv4, jak i IPv6. 580 | 581 | Można korzystać z biblioteki `Boost`, w szczególności z modułu `asio`. 582 | 583 | Rozwiązanie ma kompilować się i działać na serwerze students. 584 | 585 | Rozwiązania należy kompilować z flagami `-Wall -Wextra -Wconversion -Werror -O2`. 586 | 587 | Rozwiązania napisane w języku C++ powinny być kompilowane z flagą `-std=gnu++20`, 588 | a w języku C z flagą `-std=gnu17` przy użyciu `GCC 11.2` 589 | lub nowszego (na students w katalogu `/opt/gcc-11.2/bin`. 590 | 591 | Rozwiązanie powinno być odpowiednio sformatowane (można użyć np. `clang-format`). 592 | 593 | Dodatkowo polecamy używanie lintera (np. `clang-tidy`, który jest zintegrowany z `CLionem`) 594 | i/lub kompilowanie z flagą `-fanalyzer`. 595 | 596 | ## 5. Oddawanie rozwiązania 597 | 598 | Jako rozwiązanie można oddać tylko klienta (część A) lub tylko serwer (część B), 599 | albo obie części. 600 | 601 | Termin oddawania części A to 23.05, a termin oddawania części B to 07.06 (siódmy czerwca). 602 | 603 | Jako rozwiązanie należy dostarczyć pliki źródłowe oraz plik `makefile` ALBO `CMakeLists.txt`, które 604 | należy umieścić jako skompresowane archiwum w Moodle. Archiwum powinno zawierać 605 | tylko pliki niezbędne do zbudowania programów. Nie wolno w nim umieszczać plików 606 | binarnych ani pośrednich powstających podczas kompilowania programów. 607 | 608 | Po rozpakowaniu dostarczonego archiwum, w wyniku wykonania w jego głównym 609 | katalogu polecenia `make` (`cmake . && make` jeśli używa się `CMake`), 610 | dla części A zadania ma powstać w tym katalogu plik 611 | wykonywalny `robots-client` a dla części B zadania – plik 612 | wykonywalny `robots-server`. 613 | 614 | `makefile` powinien obsługiwać cel `clean`, który po wywołaniu kasuje 615 | wszystkie pliki powstałe podczas kompilowania. 616 | 617 | ## 6. Ocena 618 | 619 | Za rozwiązanie części A zadania można dostać maksymalnie 10 punktów. 620 | Za rozwiązanie części B zadania można dostać maksymalnie 15 punktów. 621 | Każda część zadania będzie testowana i oceniana osobno. 622 | Ocena każdej z części zadania będzie się składała z trzech składników: 623 | 624 | 1. ocena wzrokowa i manualna działania programu (20%) 625 | 2. testy automatyczne (50%) 626 | 3. jakość kodu źródłowego (30%) 627 | 628 | ### 6.1. Ocena wzrokowa i manualna działania programu 629 | 630 | - jak program reaguje, gdy zostanie wywołany z bezsensownymi argumentami? (Najlepiej jeśli wypisuje jakiś komunikat o błędzie; ważne żeby nie było segfaulta) 631 | - czy w grę rzeczywiście da się grać 632 | 633 | ### 6.2. Testy automatyczne 634 | 635 | Testy będą obejmowały m.in.: 636 | - bardzo proste scenariusze testowe (czy podłączenie gracza do serwera powoduje wysłanie odpowiedniego komunikatu do klientów, czy otrzymanie wiadomości od interfejsu powoduje wysłanie wiadomości do serwera, czy otrzymanie wiadomości od serwera powoduje wysłanie wiadomości do klienta itd., czy programy prawidłowo resolvują nazwy domenowe (np. localhost), czy można się połączyć zarówno po IPv4 jak i IPv6) 637 | - proste scenariusze testowe (symulacja krótkiej rozgrywki z jednym graczem, czy generowanie planszy odbywa się zgodnie z powyższym opisem; czy wybuch bomby jest prawidłowo obliczany, czy prawidłowo obsługiwane są znaki spoza zakresu ASCII) 638 | - złożone scenariusze testowe (symulacja kilku rozgrywek z wieloma graczami) 639 | 640 | ### 6.3. Jakość kodu źródłowego 641 | 642 | - absolutne podstawy: kod powinien być jednolicie sformatowany (najlepiej użyć do tego clang-format lub formatera wbudowanego w cliona), nie wyciekać pamięci, po skompilowaniu z parametrami `-Wall -Wextra` nie powinno być żadnych ostrzeżeń. Dodatkowo można sprawdzić sobie program przy użyciu lintera `clang-tidy` 643 | - kod powinien być sensownie podzielony na funkcje, nazwy funkcji i zmiennych powinny być znaczące (a nie np. a, b, x, y, temp) i w jednym języku 644 | - komentarze powinny być w jednym języku 645 | - „magiczne stałe” powinny być ponazywane 646 | - [„Parse, don’t validate”](https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/) 647 | - jeśli kod napisany jest w C++, to należy przestrzegać konwencji programowania w tym języku 648 | 649 | ## 7. FAQ 650 | 651 | - P: Klient może wysłać do serwera bardzo dużo ruchów (bo np. gracz wciska szybko różne strzałki), zatem nawet jak na bieżąco odczytujemy dane z socketu, to po upływie tych turn-duration milisekund, w sockecie wciąż mogą zalegać ruchy. Czy przechodzą one na następną turę? Dla przykładu, robię ruchy LPDLLPDGGLPDG, więc też takie trafią do socketu po stronie serwera, i przed upływem turn-duration ms, serwer przetworzył LPDL, więc przyjmuejmy, że w tej turze gracz robi ruch L. Czy pozostałe ruchy zalegające w sockecie (LPDGGLPDG) przechodzą na następną turę? 652 | - O: Możemy założyć, że zależy to od implementującego, bo testy automatyczne będziemy uruchamiać z dostatecznie długimi turami (rzędu 1s), żeby to się na pewno nie zdarzyło 653 | - P: Jak rozumiem, gra się zaczyna po tym jak serwer dostanie players-count komunikatów Join. Co jeśli przyjdzie więcej komunikatów Join? Mamy je zignorować? 654 | - O: Tak, serwer ignoruje komunikaty Join w momencie, gdy rozgrywka jest w trakcie 655 | - P: Odłączanie graczy rozpoznajemy po tym, że read/write z socketu TCP zwróci 0? 656 | - O: Tak 657 | - P: Kiedy mamy zapomnieć o istnieniu danego klienta? Jeśli dobrze rozumiem, to jeśli obserwator (czyli ktoś, kto nawiązał połączenie TCP z serwerem, ale nie wysłał jeszcze komunikatu Join) się odłączy to możemy zapomnieć o nim. Jeśli gracz się odłączy to ślad po nim (tj. pozycja robota itp.) istnieje do końca obecnej gry, ale po jej zakończeniu, możemy o nim zapomnieć? 658 | - O: Dokładnie tak 659 | - P: Jeśli gra się jeszcze nie rozpoczęła i podłączy się nowy klient, to jak rozumiem, należy wysłać do niego komunikat Hello i serię komunikatów AcceptedPlayer, by poinformować o tym jacy są obecnie gracze w Lobby. Jeśli w odpowiedzi na to, klient prześle Join to należy do wszystkich obserwatorów i graczy wysłać AcceptedPlayer, żeby wszyscy się dowiedzieli o nowym graczu. Dobrze rozumiem? 660 | - O: Tak właśnie 661 | - P: Co jeśli wybuchnie bomba, a na jej "drodze wybuchu" będzie znajdować się inna bomba? 662 | - O: Nic (to znaczy wybuch jednej bomby nie powoduje wybuchu innych bomb ani ich nie niszczy) 663 | - P: Rekord Player: { name: String, address: String }. Czy jest jakaś specyfikacja jak powinien wyglądać adres IPv4/IPv6? Czy można założyć, że dopuszczalny będzie po prostu output z funkcji inet_ntop? 664 | - O: Tak 665 | - P: Co zrobić, gdy GUI wyśle komunikat, którego nie da się sparsować, do klienta? 666 | - O: Zignorować 667 | - P: Co zrobić, gdy serwer wyśle komunikat, którego nie da się sparsować, do klienta? 668 | - O: Rozłączyć się, bo po niepoprawnym komunikacie nie wiadomo, kiedy miałby zacząć się poprawny komunikat 669 | - P: Co zrobić, gdy serwer wyśle komunikat, który da się sparsować, ale nie ma sensu? (np. wybucha bomba, która miała jeszcze 10 tur na timerze lub gracz zostaje przeniesiony nagle na drugi koniec planszy) 670 | - O: Serwer zawsze ma rację 671 | - P: Co ma robić klient jak jest w trakcie gry a dostanie od serwera komuikat AcceptedPlayer/GameStarted? 672 | - O: Zależy od implementacji 673 | - P: Obliczanie score w kliencie to nie jest tak proste, że się sprawdza ile razy przyszedł komunikat o zabiciu gracza, tylko score to ilość tur, gdzie występuję przynajmniej jeden taki komunikat? 674 | - O: Tak 675 | - P: Czy id graczy się resetują przy nowej grze? 676 | - O: Tak 677 | - P: Czy dwa bloki o takich samych współrzędnych są traktowane jako jeden blok, czy jako dwa różne? 678 | - O: Na danym polu może stać tylko jeden blok. 679 | - P: Czy jeśli w trakcie tury klient wyśle wiele komunikatów i część z nich jest poprawna, część nie, ale ostatni jest niepoprawny (wykonuje niedozwolony ruch), to serwer ma wziąć pod uwagę ostatni poprawny ruch wysłany w tej turze, czy zignorować wszystkie, bo ostatni wysłany był niepoprawny? 680 | - O: Wysłanie komunikatu niepoprawnego składniowo powoduje rozłączenie klienta. Komunikat poprawny składniowo, ale niemający sensu (np. join w czasie gry) jest ignorowany. Komunikat sensowny może oznaczać chęć wykonania niedozwolonego ruchu (wyjścia poza planszę, wejścia na blok, zablokowania zablokowanego pola), ale nie zmienia to faktu, że jest sensowny. W czasie gry liczy się ostatni nadesłany sensowny komunikat, niezależnie od tego, czy spowoduje poprawny ruch czy nie. 681 | - P: Czy możemy być pewni, że wiadomość od GUI przyszła z podanego adresu i wiadomości do GUI są wysyłane z podanego portu? 682 | Innymi słowy, czy wiadomości od GUI mamy odbierać przez receive, czy receive_from (i analogicznie wysyłać przez send, czy send_to)? 683 | - O: Adres i port GUI, które podaje się w kliencie, służą do wysyłania wiadomości od klienta do GUI. GUI może wysyłać komunikaty z portów efemerycznych. Ale ogólnie najlepiej nic nie zakładać o adresie GUI i być gotowym na odbieranie (poprawnych) wiadomości od kogokolwiek 684 | - P: Czy możemy założyć, że rozmiar planszy będzie zawierał się w praktycznych wymiarach? Plansza o maksymalnych wymiarach ma kilka miliardów pół co z punktu widzenia gry jest zupełnie niepraktyczne, a utrudnia implementacje logiki gry, gdy musimy założyć, że powinna działać dla takich wymiarów. Ujmując problem inaczej: czy możemy założyć, że deklaracja `T board[size_x][size_y]`, gdzie T jest typem o rozsądnej wielkości będzie poprawna? 685 | - O: Nie wydaje mi się, żeby tworzenie takiej tablicy dwuwymiarowej było do czegokolwiek potrzebne. 686 | - P: Co się dzieje, kiedy ktoś podłączy się w trakcie gry, jest to dozwolone? W treści jest zdanie: `Po podłączeniu klienta do serwera serwer wysyła do niego komunikat Hello. Jeśli rozgrywka jeszcze nie została rozpoczęta, serwer wysyła komunikaty AcceptedPlayer z informacją o podłączonych graczach. Jeśli rozgrywka już została rozpoczęta, serwer wysyła komunikat GameStarted z informacją o rozpoczęciu rozgrywki, a następnie wysyła komunikat Turn z informacją o aktualnym stanie gry. Numer tury w takim komunikacie to 0`. Czy jeśli rozgrywka trwa, a podłączy się klient-obserwator, to 687 | a) dostaje komunikat Hello, Game Started, a później kolejne tury (tak jak gracze) 688 | b) komunikat Hello, później kolejne Tury (jak gracze) 689 | c) komunikat Hello, Game Started i tury numerowane od 0? 690 | - O: a) 691 | - P: Czy klient-obserwator może wysyłać jakieś komunikaty w trakcie gry? 692 | - O: Może, ale będą ignorowane 693 | - P: Komunikat Game do GUI w polu explosions powinien przekazywać tylko wybuchy z poprzedniej tury, tak? Czyli odebranie komunikatu bomb exploded między innymi dla klienta oznacza "zapomnienie" o danej bombie i wrzucenie jej pozycji do explosions? 694 | - O: Tak 695 | - P: Klient powinien niezależnie od serwera kontrolować timer bomb i co turę zmniejszać go o 1, nawet patrząc na to, że dostanie komunikat od serwera, gdy bomba wybuchnie? 696 | - O: Tak. Jak wybuchnie bomba, która nie powinna wybuchnąć, to jest UB (ale można założyć, że serwer ma zawsze rację) 697 | - P: Mam mały problem z gui - roboty się w nim nie wyświetlają. Przesyłam przykład, plansza na której powinien być tylko robot. 698 | Ostatnia wiadomość otrzymana przez gui: 699 | ``` 700 | 2022-05-12T14:04:23.246721Z INFO gui: {"Game":{"server_name":"zabawownia","size_x":10,"size_y":10,"game_length":1000,"turn":10,"players":{"0":{"name":"michal","socket_addr":"127.0.0.1:42704"}},"player_positions":{"0":[3,3]},"blocks":[],"bombs":[],"explosions":[],"scores":{}}} 701 | ``` 702 | - O: W scores musi być player. 703 | - P: Czy klient może połączyć się z serwerem zanim otrzyma wiadomość od gui? 704 | - O: Klient łączy się z serwerem od razu po uruchomieniu 705 | - P: Czy klient może wysyłać Join wielokrotnie? 706 | - O: Może, ale to bez sensu 707 | - P: Jak powinna zachowywać się bomba wybuchająca w bloku - niszczy ten blok i nie propaguje eksplozji dalej, czy niszczy blok i rozszerza eksplozję do swojego maksymalnego zasięgu?(Oczywiście z pominięciem ingerencji innych bloków) 708 | - O: Niszczy i nie propaguje (ale roboty stojące na tym bloku są niszczone) 709 | - P: Czy po zakończeniu rozgrywki klient ma wyświetlić lobby, czy planszę, a jeśli lobby, to jakie jest zastosowanie mapy scores w wiadomości GameEnded? 710 | - O: Lobby, wiadomość jest potrzebna do testowania, bo inaczej nie da się dowiedzieć jakie były wyniki po ostatniej turze 711 | - P: Co robi klient jeżeli otrzyma wiadomość której się nie spodziewał (np. GameEnded zanim otrzymał GameStarted, Turn przed GameStarted, Hello po otrzymaniu początkowego, pierwszego Hello)? 712 | - O: UB 713 | - P: Jak mamy postępować z wiadomościami które zostały zbudowane poprawnie, ale zawierają ewidentnie niepoprawne wartości (np punkt leżący poza mapą, odwołanie do id gracza lub bomby która nie istnieje)? 714 | - O: UB, można zignorować 715 | - P: Co zrobić z wiadomością GameStarted/GameEnded, które zawierają id graczy od których nie otrzymaliśmy komunikatu AcceptedPlayer? 716 | - O: UB 717 | - P: Czy klient może wysyłać do serwera w stanie lobby wiadomości nie będące join? 718 | - O: Może, ale zostaną zignorowane (chodzi o to, że mogą np. dojść z opóźnieniem z ostatniej tury, kiedy serwer wróci już do stanu lobby) 719 | - P: Jak klient ma postępować z bombami które zostały mu przesłane, ale nie wybuchły, mimo tego, że ich timer spadł poniżej zera? 720 | - O: UB 721 | 722 | ### 06.06.2022 723 | 724 | - P: Czy można użyć biblioteki PFR https://github.com/boostorg/pfr) z Boosta nowszego niż jest na students? 725 | - O: Tak, można założyć, że `#include "boost/pfr.hpp"` będzie działać w środowisku testowym. Nie należy dołączać biblioteki do paczki z rozwiązaniem. 726 | - P: Czy można użyć jakichś innych bibliotek header-only, nie wchodzących w skład Boosta 1.74? 727 | - O: Nie 728 | 729 | ### 08.06.2022 730 | 731 | - P: Jak wygląda koniec gry? 732 | - O: Serwer wysyła Turn z turn=game_length-1 czeka na ruchy użytkowników, przetwarza, wysyła Turn z turn=game_length i od razu (nic się już nie zmienia) wysyła GameEnded z wynikami. Wówczas wyniki wysłane przez serwer powinny być takie jak obliczone w kliencie. 733 | - P: Czy można prosić o przykład, jak powinna wyglądać jakaś krótka rozgrywka? 734 | - O: Załóżmy, że serwer został uruchomiony z parametrami `-b 1 -c 1 -l 3`. Do serwera w stanie lobby podłącza się klient. Otrzymuje on komunikat `Hello`. Serwer nadal jest w stanie lobby, dopóki klient nie wyśle komunikatu `Join`. Wówczas serwer wysyła kolejno komunikat `AcceptedPlayer`, przechodzi w stan rozgrywki i wysyła kolejno: `GameStarted`, `Turn 0` (z początkową pozycją gracza i bloku). Zaczyna się tura 1. Załóżmy, że w czasie jej trwania gracz kładzie bombę. Serwer wówczas wyśle turę o numerze 1 ze zdarzeniem `BombPlaced`. W i-tej (gdzie i >= 1) turze najpierw jest faza otrzymywania wiadomości od klientów, a później podsumowanie tej fazy poprzez wysłanie komunikatu do klientów. Rozpoczyna się druga tura. Załóżmy, że teraz dołącza drugi klient, który staje się obserwatorem. Serwer wyśle do niego kolejno: `Hello`, `GameStarted`, `Turn 0`, `Turn 1` (tury wysyłane są z identycznymi zdarzeniami jak do pierwszego klienta - żeby obserwator mógł "nadrobić" stan gry). Teraz serwer wyśle do obu klientów turę o numerze 2 ze zdarzeniami `BombExploded`, `PlayerMoved` (bo gracz się "odrodzi" na innym polu - jeśli w czasie trwania drugiej tury chciał wykonać jakiś ruch, to zostanie on zignorowany, bo robot w tej turze został zniszczony) oraz `BlockDestroyed` (o ile blok został zniszczony). Rozpoczyna się trzecia tura. Załóżmy, że teraz gracz się poruszył. Wówczas serwer wyśle do obu klientów turę (o numerze 3) ze zdarzeniem `PlayerMoved` i od razu `GameEnded`. 735 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "ab_glyph" 7 | version = "0.2.15" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "24606928a235e73cdef55a0c909719cadd72fce573e5713d58cb2952d8f5794c" 10 | dependencies = [ 11 | "ab_glyph_rasterizer", 12 | "owned_ttf_parser", 13 | ] 14 | 15 | [[package]] 16 | name = "ab_glyph_rasterizer" 17 | version = "0.1.5" 18 | source = "registry+https://github.com/rust-lang/crates.io-index" 19 | checksum = "a13739d7177fbd22bb0ed28badfff9f372f8bef46c863db4e1c6248f6b223b6e" 20 | 21 | [[package]] 22 | name = "adler32" 23 | version = "1.2.0" 24 | source = "registry+https://github.com/rust-lang/crates.io-index" 25 | checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" 26 | 27 | [[package]] 28 | name = "ahash" 29 | version = "0.7.6" 30 | source = "registry+https://github.com/rust-lang/crates.io-index" 31 | checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" 32 | dependencies = [ 33 | "getrandom", 34 | "once_cell", 35 | "version_check", 36 | ] 37 | 38 | [[package]] 39 | name = "aho-corasick" 40 | version = "0.7.18" 41 | source = "registry+https://github.com/rust-lang/crates.io-index" 42 | checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" 43 | dependencies = [ 44 | "memchr", 45 | ] 46 | 47 | [[package]] 48 | name = "alsa" 49 | version = "0.6.0" 50 | source = "registry+https://github.com/rust-lang/crates.io-index" 51 | checksum = "5915f52fe2cf65e83924d037b6c5290b7cee097c6b5c8700746e6168a343fd6b" 52 | dependencies = [ 53 | "alsa-sys", 54 | "bitflags", 55 | "libc", 56 | "nix", 57 | ] 58 | 59 | [[package]] 60 | name = "alsa-sys" 61 | version = "0.3.1" 62 | source = "registry+https://github.com/rust-lang/crates.io-index" 63 | checksum = "db8fee663d06c4e303404ef5f40488a53e062f89ba8bfed81f42325aafad1527" 64 | dependencies = [ 65 | "libc", 66 | "pkg-config", 67 | ] 68 | 69 | [[package]] 70 | name = "android_log-sys" 71 | version = "0.2.0" 72 | source = "registry+https://github.com/rust-lang/crates.io-index" 73 | checksum = "85965b6739a430150bdd138e2374a98af0c3ee0d030b3bb7fc3bddff58d0102e" 74 | 75 | [[package]] 76 | name = "android_logger" 77 | version = "0.10.1" 78 | source = "registry+https://github.com/rust-lang/crates.io-index" 79 | checksum = "d9ed09b18365ed295d722d0b5ed59c01b79a826ff2d2a8f73d5ecca8e6fb2f66" 80 | dependencies = [ 81 | "android_log-sys", 82 | "env_logger", 83 | "lazy_static", 84 | "log", 85 | ] 86 | 87 | [[package]] 88 | name = "ansi_term" 89 | version = "0.12.1" 90 | source = "registry+https://github.com/rust-lang/crates.io-index" 91 | checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" 92 | dependencies = [ 93 | "winapi", 94 | ] 95 | 96 | [[package]] 97 | name = "anyhow" 98 | version = "1.0.56" 99 | source = "registry+https://github.com/rust-lang/crates.io-index" 100 | checksum = "4361135be9122e0870de935d7c439aef945b9f9ddd4199a553b5270b49c82a27" 101 | 102 | [[package]] 103 | name = "approx" 104 | version = "0.5.1" 105 | source = "registry+https://github.com/rust-lang/crates.io-index" 106 | checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" 107 | dependencies = [ 108 | "num-traits", 109 | ] 110 | 111 | [[package]] 112 | name = "arrayvec" 113 | version = "0.5.2" 114 | source = "registry+https://github.com/rust-lang/crates.io-index" 115 | checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" 116 | 117 | [[package]] 118 | name = "arrayvec" 119 | version = "0.7.2" 120 | source = "registry+https://github.com/rust-lang/crates.io-index" 121 | checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" 122 | 123 | [[package]] 124 | name = "ash" 125 | version = "0.34.0+1.2.203" 126 | source = "registry+https://github.com/rust-lang/crates.io-index" 127 | checksum = "b0f780da53d0063880d45554306489f09dd8d1bda47688b4a57bc579119356df" 128 | dependencies = [ 129 | "libloading", 130 | ] 131 | 132 | [[package]] 133 | name = "async-channel" 134 | version = "1.6.1" 135 | source = "registry+https://github.com/rust-lang/crates.io-index" 136 | checksum = "2114d64672151c0c5eaa5e131ec84a74f06e1e559830dabba01ca30605d66319" 137 | dependencies = [ 138 | "concurrent-queue", 139 | "event-listener", 140 | "futures-core", 141 | ] 142 | 143 | [[package]] 144 | name = "async-executor" 145 | version = "1.4.1" 146 | source = "registry+https://github.com/rust-lang/crates.io-index" 147 | checksum = "871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965" 148 | dependencies = [ 149 | "async-task", 150 | "concurrent-queue", 151 | "fastrand", 152 | "futures-lite", 153 | "once_cell", 154 | "slab", 155 | ] 156 | 157 | [[package]] 158 | name = "async-task" 159 | version = "4.2.0" 160 | source = "registry+https://github.com/rust-lang/crates.io-index" 161 | checksum = "30696a84d817107fc028e049980e09d5e140e8da8f1caeb17e8e950658a3cea9" 162 | 163 | [[package]] 164 | name = "atty" 165 | version = "0.2.14" 166 | source = "registry+https://github.com/rust-lang/crates.io-index" 167 | checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" 168 | dependencies = [ 169 | "hermit-abi", 170 | "libc", 171 | "winapi", 172 | ] 173 | 174 | [[package]] 175 | name = "autocfg" 176 | version = "1.1.0" 177 | source = "registry+https://github.com/rust-lang/crates.io-index" 178 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 179 | 180 | [[package]] 181 | name = "base-x" 182 | version = "0.2.8" 183 | source = "registry+https://github.com/rust-lang/crates.io-index" 184 | checksum = "a4521f3e3d031370679b3b140beb36dfe4801b09ac77e30c61941f97df3ef28b" 185 | 186 | [[package]] 187 | name = "base64" 188 | version = "0.13.0" 189 | source = "registry+https://github.com/rust-lang/crates.io-index" 190 | checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" 191 | 192 | [[package]] 193 | name = "bevy" 194 | version = "0.7.0" 195 | source = "registry+https://github.com/rust-lang/crates.io-index" 196 | checksum = "4fce306d40a111309ee61d4626efbafccdd46bb80657122c38061fa7264c08e4" 197 | dependencies = [ 198 | "bevy_dylib", 199 | "bevy_internal", 200 | ] 201 | 202 | [[package]] 203 | name = "bevy-crevice-derive" 204 | version = "0.7.0" 205 | source = "registry+https://github.com/rust-lang/crates.io-index" 206 | checksum = "191a752a01c3402deb24320acf42288bf822e5d22f19ae1d903797f02e9b0c33" 207 | dependencies = [ 208 | "bevy_macro_utils", 209 | "proc-macro2", 210 | "quote", 211 | "syn", 212 | ] 213 | 214 | [[package]] 215 | name = "bevy_animation" 216 | version = "0.7.0" 217 | source = "registry+https://github.com/rust-lang/crates.io-index" 218 | checksum = "c087569c34b168dd988e8b3409ce273661b4a58c3c534d0e381950589f59f68e" 219 | dependencies = [ 220 | "bevy_app", 221 | "bevy_asset", 222 | "bevy_core", 223 | "bevy_ecs", 224 | "bevy_hierarchy", 225 | "bevy_math", 226 | "bevy_reflect", 227 | "bevy_transform", 228 | "bevy_utils", 229 | ] 230 | 231 | [[package]] 232 | name = "bevy_app" 233 | version = "0.7.0" 234 | source = "registry+https://github.com/rust-lang/crates.io-index" 235 | checksum = "32660ae99fa3498ca379de28b7e2f447e6531b0e432bf200901efeec075553c1" 236 | dependencies = [ 237 | "bevy_derive", 238 | "bevy_ecs", 239 | "bevy_reflect", 240 | "bevy_utils", 241 | "wasm-bindgen", 242 | "web-sys", 243 | ] 244 | 245 | [[package]] 246 | name = "bevy_asset" 247 | version = "0.7.0" 248 | source = "registry+https://github.com/rust-lang/crates.io-index" 249 | checksum = "f2afd395240087924ba49c8cae2b00d007aeb1db53ee726a543b1e90dce2d3ab" 250 | dependencies = [ 251 | "anyhow", 252 | "bevy_app", 253 | "bevy_diagnostic", 254 | "bevy_ecs", 255 | "bevy_log", 256 | "bevy_reflect", 257 | "bevy_tasks", 258 | "bevy_utils", 259 | "crossbeam-channel", 260 | "downcast-rs", 261 | "js-sys", 262 | "ndk-glue 0.5.1", 263 | "notify", 264 | "parking_lot", 265 | "rand", 266 | "serde", 267 | "thiserror", 268 | "wasm-bindgen", 269 | "wasm-bindgen-futures", 270 | "web-sys", 271 | ] 272 | 273 | [[package]] 274 | name = "bevy_audio" 275 | version = "0.7.0" 276 | source = "registry+https://github.com/rust-lang/crates.io-index" 277 | checksum = "73a1c827ae837b62868539040176fb6d4daecf24983b98a0284d158e52cd21d5" 278 | dependencies = [ 279 | "anyhow", 280 | "bevy_app", 281 | "bevy_asset", 282 | "bevy_ecs", 283 | "bevy_reflect", 284 | "bevy_utils", 285 | "parking_lot", 286 | "rodio", 287 | ] 288 | 289 | [[package]] 290 | name = "bevy_core" 291 | version = "0.7.0" 292 | source = "registry+https://github.com/rust-lang/crates.io-index" 293 | checksum = "12c0f8614b6014671ab60bacb8bf681373d08b0bb15633b8ef72b895cf966d29" 294 | dependencies = [ 295 | "bevy_app", 296 | "bevy_derive", 297 | "bevy_ecs", 298 | "bevy_math", 299 | "bevy_reflect", 300 | "bevy_tasks", 301 | "bevy_utils", 302 | "bytemuck", 303 | ] 304 | 305 | [[package]] 306 | name = "bevy_core_pipeline" 307 | version = "0.7.0" 308 | source = "registry+https://github.com/rust-lang/crates.io-index" 309 | checksum = "74d570bc9310196190910a5b1ffd8c8c35bd6b73f918d0651ae3c3d4e57be9a7" 310 | dependencies = [ 311 | "bevy_app", 312 | "bevy_asset", 313 | "bevy_core", 314 | "bevy_ecs", 315 | "bevy_render", 316 | "bevy_utils", 317 | ] 318 | 319 | [[package]] 320 | name = "bevy_crevice" 321 | version = "0.7.0" 322 | source = "registry+https://github.com/rust-lang/crates.io-index" 323 | checksum = "3da0a284fb26c02cb96ef4d5bbf4de5fad7e1a901730035a61813bf64e28482e" 324 | dependencies = [ 325 | "bevy-crevice-derive", 326 | "bytemuck", 327 | "glam", 328 | "mint", 329 | ] 330 | 331 | [[package]] 332 | name = "bevy_derive" 333 | version = "0.7.0" 334 | source = "registry+https://github.com/rust-lang/crates.io-index" 335 | checksum = "6abddf2ed415f31d28a9bf9ab3c0bc857e98a722858d38dba65bdda481f8d714" 336 | dependencies = [ 337 | "bevy_macro_utils", 338 | "quote", 339 | "syn", 340 | ] 341 | 342 | [[package]] 343 | name = "bevy_diagnostic" 344 | version = "0.7.0" 345 | source = "registry+https://github.com/rust-lang/crates.io-index" 346 | checksum = "6ebf72ea058cfc379756e9da7de6861174e1860504f41e3e5a46d5b1c35d6644" 347 | dependencies = [ 348 | "bevy_app", 349 | "bevy_core", 350 | "bevy_ecs", 351 | "bevy_log", 352 | "bevy_utils", 353 | ] 354 | 355 | [[package]] 356 | name = "bevy_dylib" 357 | version = "0.7.0" 358 | source = "registry+https://github.com/rust-lang/crates.io-index" 359 | checksum = "6bf02ce7a578743cd94cb38dc7a9b405d6058a2317011744371eaa56b4d6e786" 360 | dependencies = [ 361 | "bevy_internal", 362 | ] 363 | 364 | [[package]] 365 | name = "bevy_ecs" 366 | version = "0.7.0" 367 | source = "registry+https://github.com/rust-lang/crates.io-index" 368 | checksum = "79e67dd06b14e787d2026fe6e2b63f67482afcc62284f20ea2784d8b0662e95f" 369 | dependencies = [ 370 | "async-channel", 371 | "bevy_ecs_macros", 372 | "bevy_reflect", 373 | "bevy_tasks", 374 | "bevy_utils", 375 | "downcast-rs", 376 | "fixedbitset", 377 | "fxhash", 378 | "serde", 379 | "thiserror", 380 | ] 381 | 382 | [[package]] 383 | name = "bevy_ecs_macros" 384 | version = "0.7.0" 385 | source = "registry+https://github.com/rust-lang/crates.io-index" 386 | checksum = "718923a491490bd81074492d61fc08134f9c62a29ba8666818cd7a6630421246" 387 | dependencies = [ 388 | "bevy_macro_utils", 389 | "proc-macro2", 390 | "quote", 391 | "syn", 392 | ] 393 | 394 | [[package]] 395 | name = "bevy_gilrs" 396 | version = "0.7.0" 397 | source = "registry+https://github.com/rust-lang/crates.io-index" 398 | checksum = "15b164983e8057a1a730412a7c26ccc540d9ce76d2c6ab68edd258a0baeb1762" 399 | dependencies = [ 400 | "bevy_app", 401 | "bevy_ecs", 402 | "bevy_input", 403 | "bevy_utils", 404 | "gilrs", 405 | ] 406 | 407 | [[package]] 408 | name = "bevy_gltf" 409 | version = "0.7.0" 410 | source = "registry+https://github.com/rust-lang/crates.io-index" 411 | checksum = "2e07bda7721091c1a683343d466132dc69dec65aa83d8c9e328a2fb3431f03be" 412 | dependencies = [ 413 | "anyhow", 414 | "base64", 415 | "bevy_animation", 416 | "bevy_app", 417 | "bevy_asset", 418 | "bevy_core", 419 | "bevy_ecs", 420 | "bevy_hierarchy", 421 | "bevy_log", 422 | "bevy_math", 423 | "bevy_pbr", 424 | "bevy_reflect", 425 | "bevy_render", 426 | "bevy_scene", 427 | "bevy_transform", 428 | "bevy_utils", 429 | "gltf", 430 | "percent-encoding", 431 | "thiserror", 432 | ] 433 | 434 | [[package]] 435 | name = "bevy_hierarchy" 436 | version = "0.7.0" 437 | source = "registry+https://github.com/rust-lang/crates.io-index" 438 | checksum = "2f407f152f35541a099484200afe3b0ca09ce625469e8233dcdc264d6f88e01a" 439 | dependencies = [ 440 | "bevy_app", 441 | "bevy_ecs", 442 | "bevy_reflect", 443 | "bevy_utils", 444 | "smallvec", 445 | ] 446 | 447 | [[package]] 448 | name = "bevy_input" 449 | version = "0.7.0" 450 | source = "registry+https://github.com/rust-lang/crates.io-index" 451 | checksum = "ff4ec4f6e38ef1b41ff68ec7badd6afc5c9699191e61e511c4abee91a5888afc" 452 | dependencies = [ 453 | "bevy_app", 454 | "bevy_ecs", 455 | "bevy_math", 456 | "bevy_utils", 457 | ] 458 | 459 | [[package]] 460 | name = "bevy_internal" 461 | version = "0.7.0" 462 | source = "registry+https://github.com/rust-lang/crates.io-index" 463 | checksum = "d518a8e5f526a9537fc8408a284caec7af22b23c3b23c0dee08bacc0930e2f1a" 464 | dependencies = [ 465 | "bevy_animation", 466 | "bevy_app", 467 | "bevy_asset", 468 | "bevy_audio", 469 | "bevy_core", 470 | "bevy_core_pipeline", 471 | "bevy_derive", 472 | "bevy_diagnostic", 473 | "bevy_ecs", 474 | "bevy_gilrs", 475 | "bevy_gltf", 476 | "bevy_hierarchy", 477 | "bevy_input", 478 | "bevy_log", 479 | "bevy_math", 480 | "bevy_pbr", 481 | "bevy_reflect", 482 | "bevy_render", 483 | "bevy_scene", 484 | "bevy_sprite", 485 | "bevy_tasks", 486 | "bevy_text", 487 | "bevy_transform", 488 | "bevy_ui", 489 | "bevy_utils", 490 | "bevy_window", 491 | "bevy_winit", 492 | "ndk-glue 0.5.1", 493 | ] 494 | 495 | [[package]] 496 | name = "bevy_log" 497 | version = "0.7.0" 498 | source = "registry+https://github.com/rust-lang/crates.io-index" 499 | checksum = "943ec496720ded2ff62b292d8e5fc845817a504915f41b7c5fd12b1380300f75" 500 | dependencies = [ 501 | "android_log-sys", 502 | "bevy_app", 503 | "bevy_utils", 504 | "console_error_panic_hook", 505 | "tracing-log", 506 | "tracing-subscriber", 507 | "tracing-wasm", 508 | ] 509 | 510 | [[package]] 511 | name = "bevy_macro_utils" 512 | version = "0.7.0" 513 | source = "registry+https://github.com/rust-lang/crates.io-index" 514 | checksum = "b7ddfc33a99547e36718e56e414541e461c74ec318ff987a1e9f4ff46d0dacbb" 515 | dependencies = [ 516 | "cargo-manifest", 517 | "quote", 518 | "syn", 519 | ] 520 | 521 | [[package]] 522 | name = "bevy_math" 523 | version = "0.7.0" 524 | source = "registry+https://github.com/rust-lang/crates.io-index" 525 | checksum = "20288df0f70ff258bbaffaf55209f1271a7436438591bbffc3d81e4d84b423f2" 526 | dependencies = [ 527 | "bevy_reflect", 528 | "glam", 529 | ] 530 | 531 | [[package]] 532 | name = "bevy_pbr" 533 | version = "0.7.0" 534 | source = "registry+https://github.com/rust-lang/crates.io-index" 535 | checksum = "06adee54840f18cfeda7af4cdc57608644fa840be076a562353f896bfdb9c694" 536 | dependencies = [ 537 | "bevy_app", 538 | "bevy_asset", 539 | "bevy_core", 540 | "bevy_core_pipeline", 541 | "bevy_ecs", 542 | "bevy_math", 543 | "bevy_reflect", 544 | "bevy_render", 545 | "bevy_transform", 546 | "bevy_utils", 547 | "bevy_window", 548 | "bitflags", 549 | "bytemuck", 550 | ] 551 | 552 | [[package]] 553 | name = "bevy_prototype_lyon" 554 | version = "0.5.0" 555 | source = "registry+https://github.com/rust-lang/crates.io-index" 556 | checksum = "a0a902a6ba040d8874fc8798443ccc2f920077ab8d2a869e301b5900bfdbcd66" 557 | dependencies = [ 558 | "bevy", 559 | "lyon_tessellation", 560 | "svgtypes", 561 | ] 562 | 563 | [[package]] 564 | name = "bevy_reflect" 565 | version = "0.7.0" 566 | source = "registry+https://github.com/rust-lang/crates.io-index" 567 | checksum = "4d0793107bc4b7c6bd04232d739fc8d70aa5fb313bfad6e850f91f79b2557eed" 568 | dependencies = [ 569 | "bevy_reflect_derive", 570 | "bevy_utils", 571 | "downcast-rs", 572 | "erased-serde", 573 | "glam", 574 | "parking_lot", 575 | "serde", 576 | "smallvec", 577 | "thiserror", 578 | ] 579 | 580 | [[package]] 581 | name = "bevy_reflect_derive" 582 | version = "0.7.0" 583 | source = "registry+https://github.com/rust-lang/crates.io-index" 584 | checksum = "81c88de8067d19dfde31662ee78e3ee6971e2df27715799f91b515b37a636677" 585 | dependencies = [ 586 | "bevy_macro_utils", 587 | "proc-macro2", 588 | "quote", 589 | "syn", 590 | "uuid", 591 | ] 592 | 593 | [[package]] 594 | name = "bevy_render" 595 | version = "0.7.0" 596 | source = "registry+https://github.com/rust-lang/crates.io-index" 597 | checksum = "6a358da8255b704153913c3499b3693fa5cfe13a48725ac6e76b043fa5633bc8" 598 | dependencies = [ 599 | "anyhow", 600 | "bevy_app", 601 | "bevy_asset", 602 | "bevy_core", 603 | "bevy_crevice", 604 | "bevy_derive", 605 | "bevy_ecs", 606 | "bevy_math", 607 | "bevy_reflect", 608 | "bevy_transform", 609 | "bevy_utils", 610 | "bevy_window", 611 | "bitflags", 612 | "codespan-reporting", 613 | "copyless", 614 | "downcast-rs", 615 | "futures-lite", 616 | "hex", 617 | "hexasphere", 618 | "image", 619 | "naga", 620 | "once_cell", 621 | "parking_lot", 622 | "regex", 623 | "serde", 624 | "smallvec", 625 | "thiserror", 626 | "wgpu", 627 | ] 628 | 629 | [[package]] 630 | name = "bevy_scene" 631 | version = "0.7.0" 632 | source = "registry+https://github.com/rust-lang/crates.io-index" 633 | checksum = "2ea240f2ffce9f58a5601cc5ead24111f577dc4c656452839eb1fdf4b7a28529" 634 | dependencies = [ 635 | "anyhow", 636 | "bevy_app", 637 | "bevy_asset", 638 | "bevy_ecs", 639 | "bevy_hierarchy", 640 | "bevy_reflect", 641 | "bevy_utils", 642 | "ron", 643 | "serde", 644 | "thiserror", 645 | "uuid", 646 | ] 647 | 648 | [[package]] 649 | name = "bevy_sprite" 650 | version = "0.7.0" 651 | source = "registry+https://github.com/rust-lang/crates.io-index" 652 | checksum = "5fcecfbc623410137d85a71a295ff7c16604b7be24529c9ea4b9a9881d7a142b" 653 | dependencies = [ 654 | "bevy_app", 655 | "bevy_asset", 656 | "bevy_core", 657 | "bevy_core_pipeline", 658 | "bevy_ecs", 659 | "bevy_log", 660 | "bevy_math", 661 | "bevy_reflect", 662 | "bevy_render", 663 | "bevy_transform", 664 | "bevy_utils", 665 | "bitflags", 666 | "bytemuck", 667 | "copyless", 668 | "guillotiere", 669 | "rectangle-pack", 670 | "serde", 671 | "thiserror", 672 | ] 673 | 674 | [[package]] 675 | name = "bevy_tasks" 676 | version = "0.7.0" 677 | source = "registry+https://github.com/rust-lang/crates.io-index" 678 | checksum = "db2b0f0b86c8f78c53a2d4c669522f45e725ed9d9c3d734f54ec30876494e04e" 679 | dependencies = [ 680 | "async-channel", 681 | "async-executor", 682 | "event-listener", 683 | "futures-lite", 684 | "num_cpus", 685 | "wasm-bindgen-futures", 686 | ] 687 | 688 | [[package]] 689 | name = "bevy_text" 690 | version = "0.7.0" 691 | source = "registry+https://github.com/rust-lang/crates.io-index" 692 | checksum = "a206112de011fd6baebaf476af69d87f4e38a1314b65e3c872060830d7c0b9fa" 693 | dependencies = [ 694 | "ab_glyph", 695 | "anyhow", 696 | "bevy_app", 697 | "bevy_asset", 698 | "bevy_core", 699 | "bevy_ecs", 700 | "bevy_math", 701 | "bevy_reflect", 702 | "bevy_render", 703 | "bevy_sprite", 704 | "bevy_transform", 705 | "bevy_utils", 706 | "bevy_window", 707 | "glyph_brush_layout", 708 | "serde", 709 | "thiserror", 710 | ] 711 | 712 | [[package]] 713 | name = "bevy_transform" 714 | version = "0.7.0" 715 | source = "registry+https://github.com/rust-lang/crates.io-index" 716 | checksum = "aa2f7a77900fb23f24ca312c1f8df3eb47a45161326f41e9b4ef05b039793503" 717 | dependencies = [ 718 | "bevy_app", 719 | "bevy_ecs", 720 | "bevy_hierarchy", 721 | "bevy_math", 722 | "bevy_reflect", 723 | ] 724 | 725 | [[package]] 726 | name = "bevy_ui" 727 | version = "0.7.0" 728 | source = "registry+https://github.com/rust-lang/crates.io-index" 729 | checksum = "c65e79658d8a3d4da087a6fb8b229cfe1455cda2c4e8e6305b3b44fb46fb1d30" 730 | dependencies = [ 731 | "bevy_app", 732 | "bevy_asset", 733 | "bevy_core", 734 | "bevy_core_pipeline", 735 | "bevy_derive", 736 | "bevy_ecs", 737 | "bevy_hierarchy", 738 | "bevy_input", 739 | "bevy_log", 740 | "bevy_math", 741 | "bevy_reflect", 742 | "bevy_render", 743 | "bevy_sprite", 744 | "bevy_text", 745 | "bevy_transform", 746 | "bevy_utils", 747 | "bevy_window", 748 | "bytemuck", 749 | "serde", 750 | "smallvec", 751 | "stretch", 752 | ] 753 | 754 | [[package]] 755 | name = "bevy_utils" 756 | version = "0.7.0" 757 | source = "registry+https://github.com/rust-lang/crates.io-index" 758 | checksum = "2f354c584812996febd48cc885f36b23004b49d6680e73fc95a69a2bb17a48e5" 759 | dependencies = [ 760 | "ahash", 761 | "bevy_derive", 762 | "getrandom", 763 | "hashbrown", 764 | "instant", 765 | "tracing", 766 | "uuid", 767 | ] 768 | 769 | [[package]] 770 | name = "bevy_window" 771 | version = "0.7.0" 772 | source = "registry+https://github.com/rust-lang/crates.io-index" 773 | checksum = "04fe33d177e10b2984fa90c1d19496fc6f6e7b36d4442699d359e2b4b507873d" 774 | dependencies = [ 775 | "bevy_app", 776 | "bevy_ecs", 777 | "bevy_math", 778 | "bevy_utils", 779 | "raw-window-handle", 780 | "web-sys", 781 | ] 782 | 783 | [[package]] 784 | name = "bevy_winit" 785 | version = "0.7.0" 786 | source = "registry+https://github.com/rust-lang/crates.io-index" 787 | checksum = "a7c0e3b94cc73907f8a9f82945ca006a39ed2ab401aca0974b47a007a468509f" 788 | dependencies = [ 789 | "approx", 790 | "bevy_app", 791 | "bevy_ecs", 792 | "bevy_input", 793 | "bevy_math", 794 | "bevy_utils", 795 | "bevy_window", 796 | "raw-window-handle", 797 | "wasm-bindgen", 798 | "web-sys", 799 | "winit", 800 | ] 801 | 802 | [[package]] 803 | name = "bindgen" 804 | version = "0.56.0" 805 | source = "registry+https://github.com/rust-lang/crates.io-index" 806 | checksum = "2da379dbebc0b76ef63ca68d8fc6e71c0f13e59432e0987e508c1820e6ab5239" 807 | dependencies = [ 808 | "bitflags", 809 | "cexpr", 810 | "clang-sys", 811 | "lazy_static", 812 | "lazycell", 813 | "peeking_take_while", 814 | "proc-macro2", 815 | "quote", 816 | "regex", 817 | "rustc-hash", 818 | "shlex", 819 | ] 820 | 821 | [[package]] 822 | name = "bit-set" 823 | version = "0.5.2" 824 | source = "registry+https://github.com/rust-lang/crates.io-index" 825 | checksum = "6e11e16035ea35e4e5997b393eacbf6f63983188f7a2ad25bfb13465f5ad59de" 826 | dependencies = [ 827 | "bit-vec", 828 | ] 829 | 830 | [[package]] 831 | name = "bit-vec" 832 | version = "0.6.3" 833 | source = "registry+https://github.com/rust-lang/crates.io-index" 834 | checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" 835 | 836 | [[package]] 837 | name = "bitflags" 838 | version = "1.3.2" 839 | source = "registry+https://github.com/rust-lang/crates.io-index" 840 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 841 | 842 | [[package]] 843 | name = "block" 844 | version = "0.1.6" 845 | source = "registry+https://github.com/rust-lang/crates.io-index" 846 | checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" 847 | 848 | [[package]] 849 | name = "bumpalo" 850 | version = "3.9.1" 851 | source = "registry+https://github.com/rust-lang/crates.io-index" 852 | checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" 853 | 854 | [[package]] 855 | name = "bytemuck" 856 | version = "1.9.1" 857 | source = "registry+https://github.com/rust-lang/crates.io-index" 858 | checksum = "cdead85bdec19c194affaeeb670c0e41fe23de31459efd1c174d049269cf02cc" 859 | dependencies = [ 860 | "bytemuck_derive", 861 | ] 862 | 863 | [[package]] 864 | name = "bytemuck_derive" 865 | version = "1.1.0" 866 | source = "registry+https://github.com/rust-lang/crates.io-index" 867 | checksum = "562e382481975bc61d11275ac5e62a19abd00b0547d99516a415336f183dcd0e" 868 | dependencies = [ 869 | "proc-macro2", 870 | "quote", 871 | "syn", 872 | ] 873 | 874 | [[package]] 875 | name = "byteorder" 876 | version = "1.4.3" 877 | source = "registry+https://github.com/rust-lang/crates.io-index" 878 | checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" 879 | 880 | [[package]] 881 | name = "bytes" 882 | version = "1.1.0" 883 | source = "registry+https://github.com/rust-lang/crates.io-index" 884 | checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" 885 | 886 | [[package]] 887 | name = "cache-padded" 888 | version = "1.2.0" 889 | source = "registry+https://github.com/rust-lang/crates.io-index" 890 | checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c" 891 | 892 | [[package]] 893 | name = "cargo-manifest" 894 | version = "0.2.6" 895 | source = "registry+https://github.com/rust-lang/crates.io-index" 896 | checksum = "af6d65c7592744998c67947ec771c62687c76f00179a83ffd563c0482046bb98" 897 | dependencies = [ 898 | "serde", 899 | "serde_derive", 900 | "toml", 901 | ] 902 | 903 | [[package]] 904 | name = "cc" 905 | version = "1.0.73" 906 | source = "registry+https://github.com/rust-lang/crates.io-index" 907 | checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" 908 | dependencies = [ 909 | "jobserver", 910 | ] 911 | 912 | [[package]] 913 | name = "cesu8" 914 | version = "1.1.0" 915 | source = "registry+https://github.com/rust-lang/crates.io-index" 916 | checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" 917 | 918 | [[package]] 919 | name = "cexpr" 920 | version = "0.4.0" 921 | source = "registry+https://github.com/rust-lang/crates.io-index" 922 | checksum = "f4aedb84272dbe89af497cf81375129abda4fc0a9e7c5d317498c15cc30c0d27" 923 | dependencies = [ 924 | "nom", 925 | ] 926 | 927 | [[package]] 928 | name = "cfg-if" 929 | version = "0.1.10" 930 | source = "registry+https://github.com/rust-lang/crates.io-index" 931 | checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" 932 | 933 | [[package]] 934 | name = "cfg-if" 935 | version = "1.0.0" 936 | source = "registry+https://github.com/rust-lang/crates.io-index" 937 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 938 | 939 | [[package]] 940 | name = "cfg_aliases" 941 | version = "0.1.1" 942 | source = "registry+https://github.com/rust-lang/crates.io-index" 943 | checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" 944 | 945 | [[package]] 946 | name = "clang-sys" 947 | version = "1.3.1" 948 | source = "registry+https://github.com/rust-lang/crates.io-index" 949 | checksum = "4cc00842eed744b858222c4c9faf7243aafc6d33f92f96935263ef4d8a41ce21" 950 | dependencies = [ 951 | "glob", 952 | "libc", 953 | "libloading", 954 | ] 955 | 956 | [[package]] 957 | name = "clap" 958 | version = "3.1.9" 959 | source = "registry+https://github.com/rust-lang/crates.io-index" 960 | checksum = "6aad2534fad53df1cc12519c5cda696dd3e20e6118a027e24054aea14a0bdcbe" 961 | dependencies = [ 962 | "atty", 963 | "bitflags", 964 | "clap_derive", 965 | "clap_lex", 966 | "indexmap", 967 | "lazy_static", 968 | "strsim", 969 | "termcolor", 970 | "textwrap", 971 | ] 972 | 973 | [[package]] 974 | name = "clap_derive" 975 | version = "3.1.7" 976 | source = "registry+https://github.com/rust-lang/crates.io-index" 977 | checksum = "a3aab4734e083b809aaf5794e14e756d1c798d2c69c7f7de7a09a2f5214993c1" 978 | dependencies = [ 979 | "heck", 980 | "proc-macro-error", 981 | "proc-macro2", 982 | "quote", 983 | "syn", 984 | ] 985 | 986 | [[package]] 987 | name = "clap_lex" 988 | version = "0.1.1" 989 | source = "registry+https://github.com/rust-lang/crates.io-index" 990 | checksum = "189ddd3b5d32a70b35e7686054371742a937b0d99128e76dde6340210e966669" 991 | dependencies = [ 992 | "os_str_bytes", 993 | ] 994 | 995 | [[package]] 996 | name = "cocoa" 997 | version = "0.24.0" 998 | source = "registry+https://github.com/rust-lang/crates.io-index" 999 | checksum = "6f63902e9223530efb4e26ccd0cf55ec30d592d3b42e21a28defc42a9586e832" 1000 | dependencies = [ 1001 | "bitflags", 1002 | "block", 1003 | "cocoa-foundation", 1004 | "core-foundation 0.9.3", 1005 | "core-graphics 0.22.3", 1006 | "foreign-types", 1007 | "libc", 1008 | "objc", 1009 | ] 1010 | 1011 | [[package]] 1012 | name = "cocoa-foundation" 1013 | version = "0.1.0" 1014 | source = "registry+https://github.com/rust-lang/crates.io-index" 1015 | checksum = "7ade49b65d560ca58c403a479bb396592b155c0185eada742ee323d1d68d6318" 1016 | dependencies = [ 1017 | "bitflags", 1018 | "block", 1019 | "core-foundation 0.9.3", 1020 | "core-graphics-types", 1021 | "foreign-types", 1022 | "libc", 1023 | "objc", 1024 | ] 1025 | 1026 | [[package]] 1027 | name = "codespan-reporting" 1028 | version = "0.11.1" 1029 | source = "registry+https://github.com/rust-lang/crates.io-index" 1030 | checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" 1031 | dependencies = [ 1032 | "termcolor", 1033 | "unicode-width", 1034 | ] 1035 | 1036 | [[package]] 1037 | name = "color_quant" 1038 | version = "1.1.0" 1039 | source = "registry+https://github.com/rust-lang/crates.io-index" 1040 | checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" 1041 | 1042 | [[package]] 1043 | name = "combine" 1044 | version = "4.6.3" 1045 | source = "registry+https://github.com/rust-lang/crates.io-index" 1046 | checksum = "50b727aacc797f9fc28e355d21f34709ac4fc9adecfe470ad07b8f4464f53062" 1047 | dependencies = [ 1048 | "bytes", 1049 | "memchr", 1050 | ] 1051 | 1052 | [[package]] 1053 | name = "concurrent-queue" 1054 | version = "1.2.2" 1055 | source = "registry+https://github.com/rust-lang/crates.io-index" 1056 | checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3" 1057 | dependencies = [ 1058 | "cache-padded", 1059 | ] 1060 | 1061 | [[package]] 1062 | name = "console_error_panic_hook" 1063 | version = "0.1.7" 1064 | source = "registry+https://github.com/rust-lang/crates.io-index" 1065 | checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" 1066 | dependencies = [ 1067 | "cfg-if 1.0.0", 1068 | "wasm-bindgen", 1069 | ] 1070 | 1071 | [[package]] 1072 | name = "copyless" 1073 | version = "0.1.5" 1074 | source = "registry+https://github.com/rust-lang/crates.io-index" 1075 | checksum = "a2df960f5d869b2dd8532793fde43eb5427cceb126c929747a26823ab0eeb536" 1076 | 1077 | [[package]] 1078 | name = "core-foundation" 1079 | version = "0.6.4" 1080 | source = "registry+https://github.com/rust-lang/crates.io-index" 1081 | checksum = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d" 1082 | dependencies = [ 1083 | "core-foundation-sys 0.6.2", 1084 | "libc", 1085 | ] 1086 | 1087 | [[package]] 1088 | name = "core-foundation" 1089 | version = "0.7.0" 1090 | source = "registry+https://github.com/rust-lang/crates.io-index" 1091 | checksum = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171" 1092 | dependencies = [ 1093 | "core-foundation-sys 0.7.0", 1094 | "libc", 1095 | ] 1096 | 1097 | [[package]] 1098 | name = "core-foundation" 1099 | version = "0.9.3" 1100 | source = "registry+https://github.com/rust-lang/crates.io-index" 1101 | checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" 1102 | dependencies = [ 1103 | "core-foundation-sys 0.8.3", 1104 | "libc", 1105 | ] 1106 | 1107 | [[package]] 1108 | name = "core-foundation-sys" 1109 | version = "0.6.2" 1110 | source = "registry+https://github.com/rust-lang/crates.io-index" 1111 | checksum = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" 1112 | 1113 | [[package]] 1114 | name = "core-foundation-sys" 1115 | version = "0.7.0" 1116 | source = "registry+https://github.com/rust-lang/crates.io-index" 1117 | checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" 1118 | 1119 | [[package]] 1120 | name = "core-foundation-sys" 1121 | version = "0.8.3" 1122 | source = "registry+https://github.com/rust-lang/crates.io-index" 1123 | checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" 1124 | 1125 | [[package]] 1126 | name = "core-graphics" 1127 | version = "0.19.2" 1128 | source = "registry+https://github.com/rust-lang/crates.io-index" 1129 | checksum = "b3889374e6ea6ab25dba90bb5d96202f61108058361f6dc72e8b03e6f8bbe923" 1130 | dependencies = [ 1131 | "bitflags", 1132 | "core-foundation 0.7.0", 1133 | "foreign-types", 1134 | "libc", 1135 | ] 1136 | 1137 | [[package]] 1138 | name = "core-graphics" 1139 | version = "0.22.3" 1140 | source = "registry+https://github.com/rust-lang/crates.io-index" 1141 | checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" 1142 | dependencies = [ 1143 | "bitflags", 1144 | "core-foundation 0.9.3", 1145 | "core-graphics-types", 1146 | "foreign-types", 1147 | "libc", 1148 | ] 1149 | 1150 | [[package]] 1151 | name = "core-graphics-types" 1152 | version = "0.1.1" 1153 | source = "registry+https://github.com/rust-lang/crates.io-index" 1154 | checksum = "3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b" 1155 | dependencies = [ 1156 | "bitflags", 1157 | "core-foundation 0.9.3", 1158 | "foreign-types", 1159 | "libc", 1160 | ] 1161 | 1162 | [[package]] 1163 | name = "core-video-sys" 1164 | version = "0.1.4" 1165 | source = "registry+https://github.com/rust-lang/crates.io-index" 1166 | checksum = "34ecad23610ad9757664d644e369246edde1803fcb43ed72876565098a5d3828" 1167 | dependencies = [ 1168 | "cfg-if 0.1.10", 1169 | "core-foundation-sys 0.7.0", 1170 | "core-graphics 0.19.2", 1171 | "libc", 1172 | "objc", 1173 | ] 1174 | 1175 | [[package]] 1176 | name = "coreaudio-rs" 1177 | version = "0.10.0" 1178 | source = "registry+https://github.com/rust-lang/crates.io-index" 1179 | checksum = "11894b20ebfe1ff903cbdc52259693389eea03b94918a2def2c30c3bf227ad88" 1180 | dependencies = [ 1181 | "bitflags", 1182 | "coreaudio-sys", 1183 | ] 1184 | 1185 | [[package]] 1186 | name = "coreaudio-sys" 1187 | version = "0.2.9" 1188 | source = "registry+https://github.com/rust-lang/crates.io-index" 1189 | checksum = "ca4679a59dbd8c15f064c012dfe8c1163b9453224238b59bb9328c142b8b248b" 1190 | dependencies = [ 1191 | "bindgen", 1192 | ] 1193 | 1194 | [[package]] 1195 | name = "cpal" 1196 | version = "0.13.5" 1197 | source = "registry+https://github.com/rust-lang/crates.io-index" 1198 | checksum = "74117836a5124f3629e4b474eed03e479abaf98988b4bb317e29f08cfe0e4116" 1199 | dependencies = [ 1200 | "alsa", 1201 | "core-foundation-sys 0.8.3", 1202 | "coreaudio-rs", 1203 | "jni", 1204 | "js-sys", 1205 | "lazy_static", 1206 | "libc", 1207 | "mach 0.3.2", 1208 | "ndk 0.6.0", 1209 | "ndk-glue 0.6.1", 1210 | "nix", 1211 | "oboe", 1212 | "parking_lot", 1213 | "stdweb 0.1.3", 1214 | "thiserror", 1215 | "wasm-bindgen", 1216 | "web-sys", 1217 | "winapi", 1218 | ] 1219 | 1220 | [[package]] 1221 | name = "crc32fast" 1222 | version = "1.3.2" 1223 | source = "registry+https://github.com/rust-lang/crates.io-index" 1224 | checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" 1225 | dependencies = [ 1226 | "cfg-if 1.0.0", 1227 | ] 1228 | 1229 | [[package]] 1230 | name = "crossbeam-channel" 1231 | version = "0.5.4" 1232 | source = "registry+https://github.com/rust-lang/crates.io-index" 1233 | checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53" 1234 | dependencies = [ 1235 | "cfg-if 1.0.0", 1236 | "crossbeam-utils", 1237 | ] 1238 | 1239 | [[package]] 1240 | name = "crossbeam-utils" 1241 | version = "0.8.8" 1242 | source = "registry+https://github.com/rust-lang/crates.io-index" 1243 | checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" 1244 | dependencies = [ 1245 | "cfg-if 1.0.0", 1246 | "lazy_static", 1247 | ] 1248 | 1249 | [[package]] 1250 | name = "cty" 1251 | version = "0.2.2" 1252 | source = "registry+https://github.com/rust-lang/crates.io-index" 1253 | checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" 1254 | 1255 | [[package]] 1256 | name = "d3d12" 1257 | version = "0.4.1" 1258 | source = "registry+https://github.com/rust-lang/crates.io-index" 1259 | checksum = "2daefd788d1e96e0a9d66dee4b828b883509bc3ea9ce30665f04c3246372690c" 1260 | dependencies = [ 1261 | "bitflags", 1262 | "libloading", 1263 | "winapi", 1264 | ] 1265 | 1266 | [[package]] 1267 | name = "darling" 1268 | version = "0.13.4" 1269 | source = "registry+https://github.com/rust-lang/crates.io-index" 1270 | checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" 1271 | dependencies = [ 1272 | "darling_core", 1273 | "darling_macro", 1274 | ] 1275 | 1276 | [[package]] 1277 | name = "darling_core" 1278 | version = "0.13.4" 1279 | source = "registry+https://github.com/rust-lang/crates.io-index" 1280 | checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" 1281 | dependencies = [ 1282 | "fnv", 1283 | "ident_case", 1284 | "proc-macro2", 1285 | "quote", 1286 | "strsim", 1287 | "syn", 1288 | ] 1289 | 1290 | [[package]] 1291 | name = "darling_macro" 1292 | version = "0.13.4" 1293 | source = "registry+https://github.com/rust-lang/crates.io-index" 1294 | checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" 1295 | dependencies = [ 1296 | "darling_core", 1297 | "quote", 1298 | "syn", 1299 | ] 1300 | 1301 | [[package]] 1302 | name = "deflate" 1303 | version = "0.8.6" 1304 | source = "registry+https://github.com/rust-lang/crates.io-index" 1305 | checksum = "73770f8e1fe7d64df17ca66ad28994a0a623ea497fa69486e14984e715c5d174" 1306 | dependencies = [ 1307 | "adler32", 1308 | "byteorder", 1309 | ] 1310 | 1311 | [[package]] 1312 | name = "discard" 1313 | version = "1.0.4" 1314 | source = "registry+https://github.com/rust-lang/crates.io-index" 1315 | checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" 1316 | 1317 | [[package]] 1318 | name = "dispatch" 1319 | version = "0.2.0" 1320 | source = "registry+https://github.com/rust-lang/crates.io-index" 1321 | checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" 1322 | 1323 | [[package]] 1324 | name = "downcast-rs" 1325 | version = "1.2.0" 1326 | source = "registry+https://github.com/rust-lang/crates.io-index" 1327 | checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" 1328 | 1329 | [[package]] 1330 | name = "either" 1331 | version = "1.6.1" 1332 | source = "registry+https://github.com/rust-lang/crates.io-index" 1333 | checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" 1334 | 1335 | [[package]] 1336 | name = "env_logger" 1337 | version = "0.8.4" 1338 | source = "registry+https://github.com/rust-lang/crates.io-index" 1339 | checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3" 1340 | dependencies = [ 1341 | "log", 1342 | "regex", 1343 | ] 1344 | 1345 | [[package]] 1346 | name = "erased-serde" 1347 | version = "0.3.20" 1348 | source = "registry+https://github.com/rust-lang/crates.io-index" 1349 | checksum = "ad132dd8d0d0b546348d7d86cb3191aad14b34e5f979781fc005c80d4ac67ffd" 1350 | dependencies = [ 1351 | "serde", 1352 | ] 1353 | 1354 | [[package]] 1355 | name = "euclid" 1356 | version = "0.22.7" 1357 | source = "registry+https://github.com/rust-lang/crates.io-index" 1358 | checksum = "b52c2ef4a78da0ba68fbe1fd920627411096d2ac478f7f4c9f3a54ba6705bade" 1359 | dependencies = [ 1360 | "num-traits", 1361 | ] 1362 | 1363 | [[package]] 1364 | name = "event-listener" 1365 | version = "2.5.2" 1366 | source = "registry+https://github.com/rust-lang/crates.io-index" 1367 | checksum = "77f3309417938f28bf8228fcff79a4a37103981e3e186d2ccd19c74b38f4eb71" 1368 | 1369 | [[package]] 1370 | name = "fastrand" 1371 | version = "1.7.0" 1372 | source = "registry+https://github.com/rust-lang/crates.io-index" 1373 | checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" 1374 | dependencies = [ 1375 | "instant", 1376 | ] 1377 | 1378 | [[package]] 1379 | name = "filetime" 1380 | version = "0.2.16" 1381 | source = "registry+https://github.com/rust-lang/crates.io-index" 1382 | checksum = "c0408e2626025178a6a7f7ffc05a25bc47103229f19c113755de7bf63816290c" 1383 | dependencies = [ 1384 | "cfg-if 1.0.0", 1385 | "libc", 1386 | "redox_syscall", 1387 | "winapi", 1388 | ] 1389 | 1390 | [[package]] 1391 | name = "fixedbitset" 1392 | version = "0.4.1" 1393 | source = "registry+https://github.com/rust-lang/crates.io-index" 1394 | checksum = "279fb028e20b3c4c320317955b77c5e0c9701f05a1d309905d6fc702cdc5053e" 1395 | 1396 | [[package]] 1397 | name = "float-cmp" 1398 | version = "0.5.3" 1399 | source = "registry+https://github.com/rust-lang/crates.io-index" 1400 | checksum = "75224bec9bfe1a65e2d34132933f2de7fe79900c96a0174307554244ece8150e" 1401 | 1402 | [[package]] 1403 | name = "float_next_after" 1404 | version = "0.1.5" 1405 | source = "registry+https://github.com/rust-lang/crates.io-index" 1406 | checksum = "4fc612c5837986b7104a87a0df74a5460931f1c5274be12f8d0f40aa2f30d632" 1407 | dependencies = [ 1408 | "num-traits", 1409 | ] 1410 | 1411 | [[package]] 1412 | name = "fnv" 1413 | version = "1.0.7" 1414 | source = "registry+https://github.com/rust-lang/crates.io-index" 1415 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 1416 | 1417 | [[package]] 1418 | name = "foreign-types" 1419 | version = "0.3.2" 1420 | source = "registry+https://github.com/rust-lang/crates.io-index" 1421 | checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" 1422 | dependencies = [ 1423 | "foreign-types-shared", 1424 | ] 1425 | 1426 | [[package]] 1427 | name = "foreign-types-shared" 1428 | version = "0.1.1" 1429 | source = "registry+https://github.com/rust-lang/crates.io-index" 1430 | checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" 1431 | 1432 | [[package]] 1433 | name = "fsevent-sys" 1434 | version = "4.1.0" 1435 | source = "registry+https://github.com/rust-lang/crates.io-index" 1436 | checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" 1437 | dependencies = [ 1438 | "libc", 1439 | ] 1440 | 1441 | [[package]] 1442 | name = "futures-core" 1443 | version = "0.3.21" 1444 | source = "registry+https://github.com/rust-lang/crates.io-index" 1445 | checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" 1446 | 1447 | [[package]] 1448 | name = "futures-io" 1449 | version = "0.3.21" 1450 | source = "registry+https://github.com/rust-lang/crates.io-index" 1451 | checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" 1452 | 1453 | [[package]] 1454 | name = "futures-lite" 1455 | version = "1.12.0" 1456 | source = "registry+https://github.com/rust-lang/crates.io-index" 1457 | checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48" 1458 | dependencies = [ 1459 | "fastrand", 1460 | "futures-core", 1461 | "futures-io", 1462 | "memchr", 1463 | "parking", 1464 | "pin-project-lite", 1465 | "waker-fn", 1466 | ] 1467 | 1468 | [[package]] 1469 | name = "fxhash" 1470 | version = "0.2.1" 1471 | source = "registry+https://github.com/rust-lang/crates.io-index" 1472 | checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" 1473 | dependencies = [ 1474 | "byteorder", 1475 | ] 1476 | 1477 | [[package]] 1478 | name = "getrandom" 1479 | version = "0.2.6" 1480 | source = "registry+https://github.com/rust-lang/crates.io-index" 1481 | checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" 1482 | dependencies = [ 1483 | "cfg-if 1.0.0", 1484 | "js-sys", 1485 | "libc", 1486 | "wasi 0.10.2+wasi-snapshot-preview1", 1487 | "wasm-bindgen", 1488 | ] 1489 | 1490 | [[package]] 1491 | name = "gilrs" 1492 | version = "0.8.2" 1493 | source = "registry+https://github.com/rust-lang/crates.io-index" 1494 | checksum = "1550c8bdebc993576e343d600a954654708a9a1182396ee1e805d6fe60c72909" 1495 | dependencies = [ 1496 | "fnv", 1497 | "gilrs-core", 1498 | "log", 1499 | "uuid", 1500 | "vec_map", 1501 | ] 1502 | 1503 | [[package]] 1504 | name = "gilrs-core" 1505 | version = "0.3.2" 1506 | source = "registry+https://github.com/rust-lang/crates.io-index" 1507 | checksum = "84c7262ce1e88429c9b1d847820c9d2ba00adafc955218393d9c0861d5aaab88" 1508 | dependencies = [ 1509 | "core-foundation 0.6.4", 1510 | "io-kit-sys", 1511 | "js-sys", 1512 | "libc", 1513 | "libudev-sys", 1514 | "log", 1515 | "nix", 1516 | "rusty-xinput", 1517 | "stdweb 0.4.20", 1518 | "uuid", 1519 | "vec_map", 1520 | "web-sys", 1521 | "winapi", 1522 | ] 1523 | 1524 | [[package]] 1525 | name = "glam" 1526 | version = "0.20.5" 1527 | source = "registry+https://github.com/rust-lang/crates.io-index" 1528 | checksum = "f43e957e744be03f5801a55472f593d43fabdebf25a4585db250f04d86b1675f" 1529 | dependencies = [ 1530 | "bytemuck", 1531 | "mint", 1532 | "serde", 1533 | ] 1534 | 1535 | [[package]] 1536 | name = "glob" 1537 | version = "0.3.0" 1538 | source = "registry+https://github.com/rust-lang/crates.io-index" 1539 | checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" 1540 | 1541 | [[package]] 1542 | name = "glow" 1543 | version = "0.11.2" 1544 | source = "registry+https://github.com/rust-lang/crates.io-index" 1545 | checksum = "d8bd5877156a19b8ac83a29b2306fe20537429d318f3ff0a1a2119f8d9c61919" 1546 | dependencies = [ 1547 | "js-sys", 1548 | "slotmap", 1549 | "wasm-bindgen", 1550 | "web-sys", 1551 | ] 1552 | 1553 | [[package]] 1554 | name = "gltf" 1555 | version = "1.0.0" 1556 | source = "registry+https://github.com/rust-lang/crates.io-index" 1557 | checksum = "00e0a0eace786193fc83644907097285396360e9e82e30f81a21e9b1ba836a3e" 1558 | dependencies = [ 1559 | "byteorder", 1560 | "gltf-json", 1561 | "lazy_static", 1562 | ] 1563 | 1564 | [[package]] 1565 | name = "gltf-derive" 1566 | version = "1.0.0" 1567 | source = "registry+https://github.com/rust-lang/crates.io-index" 1568 | checksum = "bdd53d6e284bb2bf02a6926e4cc4984978c1990914d6cd9deae4e31cf37cd113" 1569 | dependencies = [ 1570 | "inflections", 1571 | "proc-macro2", 1572 | "quote", 1573 | "syn", 1574 | ] 1575 | 1576 | [[package]] 1577 | name = "gltf-json" 1578 | version = "1.0.0" 1579 | source = "registry+https://github.com/rust-lang/crates.io-index" 1580 | checksum = "9949836a9ec5e7f83f76fb9bbcbc77f254a577ebbdb0820867bc11979ef97cad" 1581 | dependencies = [ 1582 | "gltf-derive", 1583 | "serde", 1584 | "serde_derive", 1585 | "serde_json", 1586 | ] 1587 | 1588 | [[package]] 1589 | name = "glyph_brush_layout" 1590 | version = "0.2.3" 1591 | source = "registry+https://github.com/rust-lang/crates.io-index" 1592 | checksum = "cc32c2334f00ca5ac3695c5009ae35da21da8c62d255b5b96d56e2597a637a38" 1593 | dependencies = [ 1594 | "ab_glyph", 1595 | "approx", 1596 | "xi-unicode", 1597 | ] 1598 | 1599 | [[package]] 1600 | name = "gpu-alloc" 1601 | version = "0.5.3" 1602 | source = "registry+https://github.com/rust-lang/crates.io-index" 1603 | checksum = "7fc59e5f710e310e76e6707f86c561dd646f69a8876da9131703b2f717de818d" 1604 | dependencies = [ 1605 | "bitflags", 1606 | "gpu-alloc-types", 1607 | ] 1608 | 1609 | [[package]] 1610 | name = "gpu-alloc-types" 1611 | version = "0.2.0" 1612 | source = "registry+https://github.com/rust-lang/crates.io-index" 1613 | checksum = "54804d0d6bc9d7f26db4eaec1ad10def69b599315f487d32c334a80d1efe67a5" 1614 | dependencies = [ 1615 | "bitflags", 1616 | ] 1617 | 1618 | [[package]] 1619 | name = "gpu-descriptor" 1620 | version = "0.2.2" 1621 | source = "registry+https://github.com/rust-lang/crates.io-index" 1622 | checksum = "a538f217be4d405ff4719a283ca68323cc2384003eca5baaa87501e821c81dda" 1623 | dependencies = [ 1624 | "bitflags", 1625 | "gpu-descriptor-types", 1626 | "hashbrown", 1627 | ] 1628 | 1629 | [[package]] 1630 | name = "gpu-descriptor-types" 1631 | version = "0.1.1" 1632 | source = "registry+https://github.com/rust-lang/crates.io-index" 1633 | checksum = "363e3677e55ad168fef68cf9de3a4a310b53124c5e784c53a1d70e92d23f2126" 1634 | dependencies = [ 1635 | "bitflags", 1636 | ] 1637 | 1638 | [[package]] 1639 | name = "guillotiere" 1640 | version = "0.6.2" 1641 | source = "registry+https://github.com/rust-lang/crates.io-index" 1642 | checksum = "b62d5865c036cb1393e23c50693df631d3f5d7bcca4c04fe4cc0fd592e74a782" 1643 | dependencies = [ 1644 | "euclid", 1645 | "svg_fmt", 1646 | ] 1647 | 1648 | [[package]] 1649 | name = "hashbrown" 1650 | version = "0.11.2" 1651 | source = "registry+https://github.com/rust-lang/crates.io-index" 1652 | checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" 1653 | dependencies = [ 1654 | "ahash", 1655 | "serde", 1656 | ] 1657 | 1658 | [[package]] 1659 | name = "heck" 1660 | version = "0.4.0" 1661 | source = "registry+https://github.com/rust-lang/crates.io-index" 1662 | checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" 1663 | 1664 | [[package]] 1665 | name = "hermit-abi" 1666 | version = "0.1.19" 1667 | source = "registry+https://github.com/rust-lang/crates.io-index" 1668 | checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" 1669 | dependencies = [ 1670 | "libc", 1671 | ] 1672 | 1673 | [[package]] 1674 | name = "hex" 1675 | version = "0.4.3" 1676 | source = "registry+https://github.com/rust-lang/crates.io-index" 1677 | checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" 1678 | 1679 | [[package]] 1680 | name = "hexasphere" 1681 | version = "7.0.0" 1682 | source = "registry+https://github.com/rust-lang/crates.io-index" 1683 | checksum = "04ab9d20ba513ff1582a7d885e91839f62cf28bef7c56b1b0428ca787315979b" 1684 | dependencies = [ 1685 | "glam", 1686 | "lazy_static", 1687 | ] 1688 | 1689 | [[package]] 1690 | name = "hexf-parse" 1691 | version = "0.2.1" 1692 | source = "registry+https://github.com/rust-lang/crates.io-index" 1693 | checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" 1694 | 1695 | [[package]] 1696 | name = "ident_case" 1697 | version = "1.0.1" 1698 | source = "registry+https://github.com/rust-lang/crates.io-index" 1699 | checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" 1700 | 1701 | [[package]] 1702 | name = "image" 1703 | version = "0.23.14" 1704 | source = "registry+https://github.com/rust-lang/crates.io-index" 1705 | checksum = "24ffcb7e7244a9bf19d35bf2883b9c080c4ced3c07a9895572178cdb8f13f6a1" 1706 | dependencies = [ 1707 | "bytemuck", 1708 | "byteorder", 1709 | "color_quant", 1710 | "num-iter", 1711 | "num-rational", 1712 | "num-traits", 1713 | "png", 1714 | "scoped_threadpool", 1715 | ] 1716 | 1717 | [[package]] 1718 | name = "indexmap" 1719 | version = "1.8.1" 1720 | source = "registry+https://github.com/rust-lang/crates.io-index" 1721 | checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee" 1722 | dependencies = [ 1723 | "autocfg", 1724 | "hashbrown", 1725 | ] 1726 | 1727 | [[package]] 1728 | name = "inflections" 1729 | version = "1.1.1" 1730 | source = "registry+https://github.com/rust-lang/crates.io-index" 1731 | checksum = "a257582fdcde896fd96463bf2d40eefea0580021c0712a0e2b028b60b47a837a" 1732 | 1733 | [[package]] 1734 | name = "inotify" 1735 | version = "0.9.6" 1736 | source = "registry+https://github.com/rust-lang/crates.io-index" 1737 | checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" 1738 | dependencies = [ 1739 | "bitflags", 1740 | "inotify-sys", 1741 | "libc", 1742 | ] 1743 | 1744 | [[package]] 1745 | name = "inotify-sys" 1746 | version = "0.1.5" 1747 | source = "registry+https://github.com/rust-lang/crates.io-index" 1748 | checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" 1749 | dependencies = [ 1750 | "libc", 1751 | ] 1752 | 1753 | [[package]] 1754 | name = "inplace_it" 1755 | version = "0.3.3" 1756 | source = "registry+https://github.com/rust-lang/crates.io-index" 1757 | checksum = "90953f308a79fe6d62a4643e51f848fbfddcd05975a38e69fdf4ab86a7baf7ca" 1758 | 1759 | [[package]] 1760 | name = "instant" 1761 | version = "0.1.12" 1762 | source = "registry+https://github.com/rust-lang/crates.io-index" 1763 | checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" 1764 | dependencies = [ 1765 | "cfg-if 1.0.0", 1766 | "js-sys", 1767 | "wasm-bindgen", 1768 | "web-sys", 1769 | ] 1770 | 1771 | [[package]] 1772 | name = "io-kit-sys" 1773 | version = "0.1.0" 1774 | source = "registry+https://github.com/rust-lang/crates.io-index" 1775 | checksum = "f21dcc74995dd4cd090b147e79789f8d65959cbfb5f0b118002db869ea3bd0a0" 1776 | dependencies = [ 1777 | "core-foundation-sys 0.6.2", 1778 | "mach 0.2.3", 1779 | ] 1780 | 1781 | [[package]] 1782 | name = "itertools" 1783 | version = "0.10.3" 1784 | source = "registry+https://github.com/rust-lang/crates.io-index" 1785 | checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" 1786 | dependencies = [ 1787 | "either", 1788 | ] 1789 | 1790 | [[package]] 1791 | name = "itoa" 1792 | version = "1.0.1" 1793 | source = "registry+https://github.com/rust-lang/crates.io-index" 1794 | checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" 1795 | 1796 | [[package]] 1797 | name = "jni" 1798 | version = "0.19.0" 1799 | source = "registry+https://github.com/rust-lang/crates.io-index" 1800 | checksum = "c6df18c2e3db7e453d3c6ac5b3e9d5182664d28788126d39b91f2d1e22b017ec" 1801 | dependencies = [ 1802 | "cesu8", 1803 | "combine", 1804 | "jni-sys", 1805 | "log", 1806 | "thiserror", 1807 | "walkdir", 1808 | ] 1809 | 1810 | [[package]] 1811 | name = "jni-sys" 1812 | version = "0.3.0" 1813 | source = "registry+https://github.com/rust-lang/crates.io-index" 1814 | checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" 1815 | 1816 | [[package]] 1817 | name = "jobserver" 1818 | version = "0.1.24" 1819 | source = "registry+https://github.com/rust-lang/crates.io-index" 1820 | checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa" 1821 | dependencies = [ 1822 | "libc", 1823 | ] 1824 | 1825 | [[package]] 1826 | name = "js-sys" 1827 | version = "0.3.57" 1828 | source = "registry+https://github.com/rust-lang/crates.io-index" 1829 | checksum = "671a26f820db17c2a2750743f1dd03bafd15b98c9f30c7c2628c024c05d73397" 1830 | dependencies = [ 1831 | "wasm-bindgen", 1832 | ] 1833 | 1834 | [[package]] 1835 | name = "khronos-egl" 1836 | version = "4.1.0" 1837 | source = "registry+https://github.com/rust-lang/crates.io-index" 1838 | checksum = "8c2352bd1d0bceb871cb9d40f24360c8133c11d7486b68b5381c1dd1a32015e3" 1839 | dependencies = [ 1840 | "libc", 1841 | "libloading", 1842 | ] 1843 | 1844 | [[package]] 1845 | name = "kqueue" 1846 | version = "1.0.5" 1847 | source = "registry+https://github.com/rust-lang/crates.io-index" 1848 | checksum = "97caf428b83f7c86809b7450722cd1f2b1fc7fb23aa7b9dee7e72ed14d048352" 1849 | dependencies = [ 1850 | "kqueue-sys", 1851 | "libc", 1852 | ] 1853 | 1854 | [[package]] 1855 | name = "kqueue-sys" 1856 | version = "1.0.3" 1857 | source = "registry+https://github.com/rust-lang/crates.io-index" 1858 | checksum = "8367585489f01bc55dd27404dcf56b95e6da061a256a666ab23be9ba96a2e587" 1859 | dependencies = [ 1860 | "bitflags", 1861 | "libc", 1862 | ] 1863 | 1864 | [[package]] 1865 | name = "lazy_static" 1866 | version = "1.4.0" 1867 | source = "registry+https://github.com/rust-lang/crates.io-index" 1868 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 1869 | 1870 | [[package]] 1871 | name = "lazycell" 1872 | version = "1.3.0" 1873 | source = "registry+https://github.com/rust-lang/crates.io-index" 1874 | checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" 1875 | 1876 | [[package]] 1877 | name = "lewton" 1878 | version = "0.10.2" 1879 | source = "registry+https://github.com/rust-lang/crates.io-index" 1880 | checksum = "777b48df9aaab155475a83a7df3070395ea1ac6902f5cd062b8f2b028075c030" 1881 | dependencies = [ 1882 | "byteorder", 1883 | "ogg", 1884 | "tinyvec", 1885 | ] 1886 | 1887 | [[package]] 1888 | name = "libc" 1889 | version = "0.2.123" 1890 | source = "registry+https://github.com/rust-lang/crates.io-index" 1891 | checksum = "cb691a747a7ab48abc15c5b42066eaafde10dc427e3b6ee2a1cf43db04c763bd" 1892 | 1893 | [[package]] 1894 | name = "libloading" 1895 | version = "0.7.3" 1896 | source = "registry+https://github.com/rust-lang/crates.io-index" 1897 | checksum = "efbc0f03f9a775e9f6aed295c6a1ba2253c5757a9e03d55c6caa46a681abcddd" 1898 | dependencies = [ 1899 | "cfg-if 1.0.0", 1900 | "winapi", 1901 | ] 1902 | 1903 | [[package]] 1904 | name = "libm" 1905 | version = "0.1.4" 1906 | source = "registry+https://github.com/rust-lang/crates.io-index" 1907 | checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a" 1908 | 1909 | [[package]] 1910 | name = "libudev-sys" 1911 | version = "0.1.4" 1912 | source = "registry+https://github.com/rust-lang/crates.io-index" 1913 | checksum = "3c8469b4a23b962c1396b9b451dda50ef5b283e8dd309d69033475fa9b334324" 1914 | dependencies = [ 1915 | "libc", 1916 | "pkg-config", 1917 | ] 1918 | 1919 | [[package]] 1920 | name = "lock_api" 1921 | version = "0.4.7" 1922 | source = "registry+https://github.com/rust-lang/crates.io-index" 1923 | checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" 1924 | dependencies = [ 1925 | "autocfg", 1926 | "scopeguard", 1927 | ] 1928 | 1929 | [[package]] 1930 | name = "log" 1931 | version = "0.4.16" 1932 | source = "registry+https://github.com/rust-lang/crates.io-index" 1933 | checksum = "6389c490849ff5bc16be905ae24bc913a9c8892e19b2341dbc175e14c341c2b8" 1934 | dependencies = [ 1935 | "cfg-if 1.0.0", 1936 | ] 1937 | 1938 | [[package]] 1939 | name = "lyon_geom" 1940 | version = "0.17.6" 1941 | source = "registry+https://github.com/rust-lang/crates.io-index" 1942 | checksum = "ce99ce77c22bfd8f39a95b9c749dffbfc3e2491ea30c874764c801a8b1485489" 1943 | dependencies = [ 1944 | "arrayvec 0.5.2", 1945 | "euclid", 1946 | "num-traits", 1947 | ] 1948 | 1949 | [[package]] 1950 | name = "lyon_path" 1951 | version = "0.17.7" 1952 | source = "registry+https://github.com/rust-lang/crates.io-index" 1953 | checksum = "5b0a59fdf767ca0d887aa61d1b48d4bbf6a124c1a45503593f7d38ab945bfbc0" 1954 | dependencies = [ 1955 | "lyon_geom", 1956 | ] 1957 | 1958 | [[package]] 1959 | name = "lyon_tessellation" 1960 | version = "0.17.10" 1961 | source = "registry+https://github.com/rust-lang/crates.io-index" 1962 | checksum = "7230e08dd0638048e46f387f255dbe7a7344a3e6705beab53242b5af25635760" 1963 | dependencies = [ 1964 | "float_next_after", 1965 | "lyon_path", 1966 | ] 1967 | 1968 | [[package]] 1969 | name = "mach" 1970 | version = "0.2.3" 1971 | source = "registry+https://github.com/rust-lang/crates.io-index" 1972 | checksum = "86dd2487cdfea56def77b88438a2c915fb45113c5319bfe7e14306ca4cd0b0e1" 1973 | dependencies = [ 1974 | "libc", 1975 | ] 1976 | 1977 | [[package]] 1978 | name = "mach" 1979 | version = "0.3.2" 1980 | source = "registry+https://github.com/rust-lang/crates.io-index" 1981 | checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa" 1982 | dependencies = [ 1983 | "libc", 1984 | ] 1985 | 1986 | [[package]] 1987 | name = "malloc_buf" 1988 | version = "0.0.6" 1989 | source = "registry+https://github.com/rust-lang/crates.io-index" 1990 | checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" 1991 | dependencies = [ 1992 | "libc", 1993 | ] 1994 | 1995 | [[package]] 1996 | name = "matchers" 1997 | version = "0.1.0" 1998 | source = "registry+https://github.com/rust-lang/crates.io-index" 1999 | checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" 2000 | dependencies = [ 2001 | "regex-automata", 2002 | ] 2003 | 2004 | [[package]] 2005 | name = "memchr" 2006 | version = "2.4.1" 2007 | source = "registry+https://github.com/rust-lang/crates.io-index" 2008 | checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" 2009 | 2010 | [[package]] 2011 | name = "memoffset" 2012 | version = "0.6.5" 2013 | source = "registry+https://github.com/rust-lang/crates.io-index" 2014 | checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" 2015 | dependencies = [ 2016 | "autocfg", 2017 | ] 2018 | 2019 | [[package]] 2020 | name = "metal" 2021 | version = "0.23.1" 2022 | source = "registry+https://github.com/rust-lang/crates.io-index" 2023 | checksum = "e0514f491f4cc03632ab399ee01e2c1c1b12d3e1cf2d667c1ff5f87d6dcd2084" 2024 | dependencies = [ 2025 | "bitflags", 2026 | "block", 2027 | "core-graphics-types", 2028 | "foreign-types", 2029 | "log", 2030 | "objc", 2031 | ] 2032 | 2033 | [[package]] 2034 | name = "miniz_oxide" 2035 | version = "0.3.7" 2036 | source = "registry+https://github.com/rust-lang/crates.io-index" 2037 | checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435" 2038 | dependencies = [ 2039 | "adler32", 2040 | ] 2041 | 2042 | [[package]] 2043 | name = "mint" 2044 | version = "0.5.9" 2045 | source = "registry+https://github.com/rust-lang/crates.io-index" 2046 | checksum = "e53debba6bda7a793e5f99b8dacf19e626084f525f7829104ba9898f367d85ff" 2047 | 2048 | [[package]] 2049 | name = "mio" 2050 | version = "0.7.14" 2051 | source = "registry+https://github.com/rust-lang/crates.io-index" 2052 | checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" 2053 | dependencies = [ 2054 | "libc", 2055 | "log", 2056 | "miow", 2057 | "ntapi", 2058 | "winapi", 2059 | ] 2060 | 2061 | [[package]] 2062 | name = "mio" 2063 | version = "0.8.2" 2064 | source = "registry+https://github.com/rust-lang/crates.io-index" 2065 | checksum = "52da4364ffb0e4fe33a9841a98a3f3014fb964045ce4f7a45a398243c8d6b0c9" 2066 | dependencies = [ 2067 | "libc", 2068 | "log", 2069 | "miow", 2070 | "ntapi", 2071 | "wasi 0.11.0+wasi-snapshot-preview1", 2072 | "winapi", 2073 | ] 2074 | 2075 | [[package]] 2076 | name = "miow" 2077 | version = "0.3.7" 2078 | source = "registry+https://github.com/rust-lang/crates.io-index" 2079 | checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" 2080 | dependencies = [ 2081 | "winapi", 2082 | ] 2083 | 2084 | [[package]] 2085 | name = "naga" 2086 | version = "0.8.5" 2087 | source = "registry+https://github.com/rust-lang/crates.io-index" 2088 | checksum = "3012f2dbcc79e8e0b5825a4836a7106a75dd9b2fe42c528163be0f572538c705" 2089 | dependencies = [ 2090 | "bit-set", 2091 | "bitflags", 2092 | "codespan-reporting", 2093 | "hexf-parse", 2094 | "indexmap", 2095 | "log", 2096 | "num-traits", 2097 | "petgraph", 2098 | "pp-rs", 2099 | "rustc-hash", 2100 | "spirv", 2101 | "thiserror", 2102 | ] 2103 | 2104 | [[package]] 2105 | name = "ndk" 2106 | version = "0.5.0" 2107 | source = "registry+https://github.com/rust-lang/crates.io-index" 2108 | checksum = "96d868f654c72e75f8687572699cdabe755f03effbb62542768e995d5b8d699d" 2109 | dependencies = [ 2110 | "bitflags", 2111 | "jni-sys", 2112 | "ndk-sys 0.2.2", 2113 | "num_enum", 2114 | "thiserror", 2115 | ] 2116 | 2117 | [[package]] 2118 | name = "ndk" 2119 | version = "0.6.0" 2120 | source = "registry+https://github.com/rust-lang/crates.io-index" 2121 | checksum = "2032c77e030ddee34a6787a64166008da93f6a352b629261d0fee232b8742dd4" 2122 | dependencies = [ 2123 | "bitflags", 2124 | "jni-sys", 2125 | "ndk-sys 0.3.0", 2126 | "num_enum", 2127 | "thiserror", 2128 | ] 2129 | 2130 | [[package]] 2131 | name = "ndk-context" 2132 | version = "0.1.0" 2133 | source = "registry+https://github.com/rust-lang/crates.io-index" 2134 | checksum = "4e3c5cc68637e21fe8f077f6a1c9e0b9ca495bb74895226b476310f613325884" 2135 | 2136 | [[package]] 2137 | name = "ndk-glue" 2138 | version = "0.5.1" 2139 | source = "registry+https://github.com/rust-lang/crates.io-index" 2140 | checksum = "a1c68f70683c5fc9a747a383744206cd371741b2f0b31781ab6770487ec572e2" 2141 | dependencies = [ 2142 | "android_logger", 2143 | "lazy_static", 2144 | "libc", 2145 | "log", 2146 | "ndk 0.5.0", 2147 | "ndk-context", 2148 | "ndk-macro", 2149 | "ndk-sys 0.2.2", 2150 | ] 2151 | 2152 | [[package]] 2153 | name = "ndk-glue" 2154 | version = "0.6.1" 2155 | source = "registry+https://github.com/rust-lang/crates.io-index" 2156 | checksum = "d9ffb7443daba48349d545028777ca98853b018b4c16624aa01223bc29e078da" 2157 | dependencies = [ 2158 | "lazy_static", 2159 | "libc", 2160 | "log", 2161 | "ndk 0.6.0", 2162 | "ndk-context", 2163 | "ndk-macro", 2164 | "ndk-sys 0.3.0", 2165 | ] 2166 | 2167 | [[package]] 2168 | name = "ndk-macro" 2169 | version = "0.3.0" 2170 | source = "registry+https://github.com/rust-lang/crates.io-index" 2171 | checksum = "0df7ac00c4672f9d5aece54ee3347520b7e20f158656c7db2e6de01902eb7a6c" 2172 | dependencies = [ 2173 | "darling", 2174 | "proc-macro-crate", 2175 | "proc-macro2", 2176 | "quote", 2177 | "syn", 2178 | ] 2179 | 2180 | [[package]] 2181 | name = "ndk-sys" 2182 | version = "0.2.2" 2183 | source = "registry+https://github.com/rust-lang/crates.io-index" 2184 | checksum = "e1bcdd74c20ad5d95aacd60ef9ba40fdf77f767051040541df557b7a9b2a2121" 2185 | 2186 | [[package]] 2187 | name = "ndk-sys" 2188 | version = "0.3.0" 2189 | source = "registry+https://github.com/rust-lang/crates.io-index" 2190 | checksum = "6e5a6ae77c8ee183dcbbba6150e2e6b9f3f4196a7666c02a715a95692ec1fa97" 2191 | dependencies = [ 2192 | "jni-sys", 2193 | ] 2194 | 2195 | [[package]] 2196 | name = "nix" 2197 | version = "0.23.1" 2198 | source = "registry+https://github.com/rust-lang/crates.io-index" 2199 | checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6" 2200 | dependencies = [ 2201 | "bitflags", 2202 | "cc", 2203 | "cfg-if 1.0.0", 2204 | "libc", 2205 | "memoffset", 2206 | ] 2207 | 2208 | [[package]] 2209 | name = "nom" 2210 | version = "5.1.2" 2211 | source = "registry+https://github.com/rust-lang/crates.io-index" 2212 | checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af" 2213 | dependencies = [ 2214 | "memchr", 2215 | "version_check", 2216 | ] 2217 | 2218 | [[package]] 2219 | name = "notify" 2220 | version = "5.0.0-pre.11" 2221 | source = "registry+https://github.com/rust-lang/crates.io-index" 2222 | checksum = "c614e7ed2b1cf82ec99aeffd8cf6225ef5021b9951148eb161393c394855032c" 2223 | dependencies = [ 2224 | "bitflags", 2225 | "crossbeam-channel", 2226 | "filetime", 2227 | "fsevent-sys", 2228 | "inotify", 2229 | "kqueue", 2230 | "libc", 2231 | "mio 0.7.14", 2232 | "walkdir", 2233 | "winapi", 2234 | ] 2235 | 2236 | [[package]] 2237 | name = "ntapi" 2238 | version = "0.3.7" 2239 | source = "registry+https://github.com/rust-lang/crates.io-index" 2240 | checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f" 2241 | dependencies = [ 2242 | "winapi", 2243 | ] 2244 | 2245 | [[package]] 2246 | name = "num-derive" 2247 | version = "0.3.3" 2248 | source = "registry+https://github.com/rust-lang/crates.io-index" 2249 | checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" 2250 | dependencies = [ 2251 | "proc-macro2", 2252 | "quote", 2253 | "syn", 2254 | ] 2255 | 2256 | [[package]] 2257 | name = "num-integer" 2258 | version = "0.1.44" 2259 | source = "registry+https://github.com/rust-lang/crates.io-index" 2260 | checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" 2261 | dependencies = [ 2262 | "autocfg", 2263 | "num-traits", 2264 | ] 2265 | 2266 | [[package]] 2267 | name = "num-iter" 2268 | version = "0.1.42" 2269 | source = "registry+https://github.com/rust-lang/crates.io-index" 2270 | checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59" 2271 | dependencies = [ 2272 | "autocfg", 2273 | "num-integer", 2274 | "num-traits", 2275 | ] 2276 | 2277 | [[package]] 2278 | name = "num-rational" 2279 | version = "0.3.2" 2280 | source = "registry+https://github.com/rust-lang/crates.io-index" 2281 | checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" 2282 | dependencies = [ 2283 | "autocfg", 2284 | "num-integer", 2285 | "num-traits", 2286 | ] 2287 | 2288 | [[package]] 2289 | name = "num-traits" 2290 | version = "0.2.14" 2291 | source = "registry+https://github.com/rust-lang/crates.io-index" 2292 | checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" 2293 | dependencies = [ 2294 | "autocfg", 2295 | ] 2296 | 2297 | [[package]] 2298 | name = "num_cpus" 2299 | version = "1.13.1" 2300 | source = "registry+https://github.com/rust-lang/crates.io-index" 2301 | checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" 2302 | dependencies = [ 2303 | "hermit-abi", 2304 | "libc", 2305 | ] 2306 | 2307 | [[package]] 2308 | name = "num_enum" 2309 | version = "0.5.7" 2310 | source = "registry+https://github.com/rust-lang/crates.io-index" 2311 | checksum = "cf5395665662ef45796a4ff5486c5d41d29e0c09640af4c5f17fd94ee2c119c9" 2312 | dependencies = [ 2313 | "num_enum_derive", 2314 | ] 2315 | 2316 | [[package]] 2317 | name = "num_enum_derive" 2318 | version = "0.5.7" 2319 | source = "registry+https://github.com/rust-lang/crates.io-index" 2320 | checksum = "3b0498641e53dd6ac1a4f22547548caa6864cc4933784319cd1775271c5a46ce" 2321 | dependencies = [ 2322 | "proc-macro-crate", 2323 | "proc-macro2", 2324 | "quote", 2325 | "syn", 2326 | ] 2327 | 2328 | [[package]] 2329 | name = "objc" 2330 | version = "0.2.7" 2331 | source = "registry+https://github.com/rust-lang/crates.io-index" 2332 | checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" 2333 | dependencies = [ 2334 | "malloc_buf", 2335 | "objc_exception", 2336 | ] 2337 | 2338 | [[package]] 2339 | name = "objc_exception" 2340 | version = "0.1.2" 2341 | source = "registry+https://github.com/rust-lang/crates.io-index" 2342 | checksum = "ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4" 2343 | dependencies = [ 2344 | "cc", 2345 | ] 2346 | 2347 | [[package]] 2348 | name = "oboe" 2349 | version = "0.4.5" 2350 | source = "registry+https://github.com/rust-lang/crates.io-index" 2351 | checksum = "2463c8f2e19b4e0d0710a21f8e4011501ff28db1c95d7a5482a553b2100502d2" 2352 | dependencies = [ 2353 | "jni", 2354 | "ndk 0.6.0", 2355 | "ndk-glue 0.6.1", 2356 | "num-derive", 2357 | "num-traits", 2358 | "oboe-sys", 2359 | ] 2360 | 2361 | [[package]] 2362 | name = "oboe-sys" 2363 | version = "0.4.5" 2364 | source = "registry+https://github.com/rust-lang/crates.io-index" 2365 | checksum = "3370abb7372ed744232c12954d920d1a40f1c4686de9e79e800021ef492294bd" 2366 | dependencies = [ 2367 | "cc", 2368 | ] 2369 | 2370 | [[package]] 2371 | name = "ogg" 2372 | version = "0.8.0" 2373 | source = "registry+https://github.com/rust-lang/crates.io-index" 2374 | checksum = "6951b4e8bf21c8193da321bcce9c9dd2e13c858fe078bf9054a288b419ae5d6e" 2375 | dependencies = [ 2376 | "byteorder", 2377 | ] 2378 | 2379 | [[package]] 2380 | name = "once_cell" 2381 | version = "1.10.0" 2382 | source = "registry+https://github.com/rust-lang/crates.io-index" 2383 | checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9" 2384 | 2385 | [[package]] 2386 | name = "os_str_bytes" 2387 | version = "6.0.0" 2388 | source = "registry+https://github.com/rust-lang/crates.io-index" 2389 | checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" 2390 | 2391 | [[package]] 2392 | name = "owned_ttf_parser" 2393 | version = "0.15.0" 2394 | source = "registry+https://github.com/rust-lang/crates.io-index" 2395 | checksum = "4fb1e509cfe7a12db2a90bfa057dfcdbc55a347f5da677c506b53dd099cfec9d" 2396 | dependencies = [ 2397 | "ttf-parser", 2398 | ] 2399 | 2400 | [[package]] 2401 | name = "parking" 2402 | version = "2.0.0" 2403 | source = "registry+https://github.com/rust-lang/crates.io-index" 2404 | checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" 2405 | 2406 | [[package]] 2407 | name = "parking_lot" 2408 | version = "0.11.2" 2409 | source = "registry+https://github.com/rust-lang/crates.io-index" 2410 | checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" 2411 | dependencies = [ 2412 | "instant", 2413 | "lock_api", 2414 | "parking_lot_core", 2415 | ] 2416 | 2417 | [[package]] 2418 | name = "parking_lot_core" 2419 | version = "0.8.5" 2420 | source = "registry+https://github.com/rust-lang/crates.io-index" 2421 | checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" 2422 | dependencies = [ 2423 | "cfg-if 1.0.0", 2424 | "instant", 2425 | "libc", 2426 | "redox_syscall", 2427 | "smallvec", 2428 | "winapi", 2429 | ] 2430 | 2431 | [[package]] 2432 | name = "peeking_take_while" 2433 | version = "0.1.2" 2434 | source = "registry+https://github.com/rust-lang/crates.io-index" 2435 | checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" 2436 | 2437 | [[package]] 2438 | name = "percent-encoding" 2439 | version = "2.1.0" 2440 | source = "registry+https://github.com/rust-lang/crates.io-index" 2441 | checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" 2442 | 2443 | [[package]] 2444 | name = "petgraph" 2445 | version = "0.6.0" 2446 | source = "registry+https://github.com/rust-lang/crates.io-index" 2447 | checksum = "4a13a2fa9d0b63e5f22328828741e523766fff0ee9e779316902290dff3f824f" 2448 | dependencies = [ 2449 | "fixedbitset", 2450 | "indexmap", 2451 | ] 2452 | 2453 | [[package]] 2454 | name = "pin-project-lite" 2455 | version = "0.2.8" 2456 | source = "registry+https://github.com/rust-lang/crates.io-index" 2457 | checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" 2458 | 2459 | [[package]] 2460 | name = "pkg-config" 2461 | version = "0.3.25" 2462 | source = "registry+https://github.com/rust-lang/crates.io-index" 2463 | checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" 2464 | 2465 | [[package]] 2466 | name = "png" 2467 | version = "0.16.8" 2468 | source = "registry+https://github.com/rust-lang/crates.io-index" 2469 | checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6" 2470 | dependencies = [ 2471 | "bitflags", 2472 | "crc32fast", 2473 | "deflate", 2474 | "miniz_oxide", 2475 | ] 2476 | 2477 | [[package]] 2478 | name = "pp-rs" 2479 | version = "0.2.1" 2480 | source = "registry+https://github.com/rust-lang/crates.io-index" 2481 | checksum = "bb458bb7f6e250e6eb79d5026badc10a3ebb8f9a15d1fff0f13d17c71f4d6dee" 2482 | dependencies = [ 2483 | "unicode-xid", 2484 | ] 2485 | 2486 | [[package]] 2487 | name = "ppv-lite86" 2488 | version = "0.2.16" 2489 | source = "registry+https://github.com/rust-lang/crates.io-index" 2490 | checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" 2491 | 2492 | [[package]] 2493 | name = "proc-macro-crate" 2494 | version = "1.1.3" 2495 | source = "registry+https://github.com/rust-lang/crates.io-index" 2496 | checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a" 2497 | dependencies = [ 2498 | "thiserror", 2499 | "toml", 2500 | ] 2501 | 2502 | [[package]] 2503 | name = "proc-macro-error" 2504 | version = "1.0.4" 2505 | source = "registry+https://github.com/rust-lang/crates.io-index" 2506 | checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 2507 | dependencies = [ 2508 | "proc-macro-error-attr", 2509 | "proc-macro2", 2510 | "quote", 2511 | "syn", 2512 | "version_check", 2513 | ] 2514 | 2515 | [[package]] 2516 | name = "proc-macro-error-attr" 2517 | version = "1.0.4" 2518 | source = "registry+https://github.com/rust-lang/crates.io-index" 2519 | checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 2520 | dependencies = [ 2521 | "proc-macro2", 2522 | "quote", 2523 | "version_check", 2524 | ] 2525 | 2526 | [[package]] 2527 | name = "proc-macro2" 2528 | version = "1.0.37" 2529 | source = "registry+https://github.com/rust-lang/crates.io-index" 2530 | checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1" 2531 | dependencies = [ 2532 | "unicode-xid", 2533 | ] 2534 | 2535 | [[package]] 2536 | name = "profiling" 2537 | version = "1.0.5" 2538 | source = "registry+https://github.com/rust-lang/crates.io-index" 2539 | checksum = "9145ac0af1d93c638c98c40cf7d25665f427b2a44ad0a99b1dccf3e2f25bb987" 2540 | 2541 | [[package]] 2542 | name = "quote" 2543 | version = "1.0.18" 2544 | source = "registry+https://github.com/rust-lang/crates.io-index" 2545 | checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" 2546 | dependencies = [ 2547 | "proc-macro2", 2548 | ] 2549 | 2550 | [[package]] 2551 | name = "rand" 2552 | version = "0.8.5" 2553 | source = "registry+https://github.com/rust-lang/crates.io-index" 2554 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 2555 | dependencies = [ 2556 | "libc", 2557 | "rand_chacha", 2558 | "rand_core", 2559 | ] 2560 | 2561 | [[package]] 2562 | name = "rand_chacha" 2563 | version = "0.3.1" 2564 | source = "registry+https://github.com/rust-lang/crates.io-index" 2565 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 2566 | dependencies = [ 2567 | "ppv-lite86", 2568 | "rand_core", 2569 | ] 2570 | 2571 | [[package]] 2572 | name = "rand_core" 2573 | version = "0.6.3" 2574 | source = "registry+https://github.com/rust-lang/crates.io-index" 2575 | checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" 2576 | dependencies = [ 2577 | "getrandom", 2578 | ] 2579 | 2580 | [[package]] 2581 | name = "range-alloc" 2582 | version = "0.1.2" 2583 | source = "registry+https://github.com/rust-lang/crates.io-index" 2584 | checksum = "63e935c45e09cc6dcf00d2f0b2d630a58f4095320223d47fc68918722f0538b6" 2585 | 2586 | [[package]] 2587 | name = "raw-window-handle" 2588 | version = "0.4.3" 2589 | source = "registry+https://github.com/rust-lang/crates.io-index" 2590 | checksum = "b800beb9b6e7d2df1fe337c9e3d04e3af22a124460fb4c30fcc22c9117cefb41" 2591 | dependencies = [ 2592 | "cty", 2593 | ] 2594 | 2595 | [[package]] 2596 | name = "rectangle-pack" 2597 | version = "0.4.2" 2598 | source = "registry+https://github.com/rust-lang/crates.io-index" 2599 | checksum = "a0d463f2884048e7153449a55166f91028d5b0ea53c79377099ce4e8cf0cf9bb" 2600 | 2601 | [[package]] 2602 | name = "redox_syscall" 2603 | version = "0.2.13" 2604 | source = "registry+https://github.com/rust-lang/crates.io-index" 2605 | checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" 2606 | dependencies = [ 2607 | "bitflags", 2608 | ] 2609 | 2610 | [[package]] 2611 | name = "regex" 2612 | version = "1.5.5" 2613 | source = "registry+https://github.com/rust-lang/crates.io-index" 2614 | checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" 2615 | dependencies = [ 2616 | "aho-corasick", 2617 | "memchr", 2618 | "regex-syntax", 2619 | ] 2620 | 2621 | [[package]] 2622 | name = "regex-automata" 2623 | version = "0.1.10" 2624 | source = "registry+https://github.com/rust-lang/crates.io-index" 2625 | checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" 2626 | dependencies = [ 2627 | "regex-syntax", 2628 | ] 2629 | 2630 | [[package]] 2631 | name = "regex-syntax" 2632 | version = "0.6.25" 2633 | source = "registry+https://github.com/rust-lang/crates.io-index" 2634 | checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" 2635 | 2636 | [[package]] 2637 | name = "renderdoc-sys" 2638 | version = "0.7.1" 2639 | source = "registry+https://github.com/rust-lang/crates.io-index" 2640 | checksum = "f1382d1f0a252c4bf97dc20d979a2fdd05b024acd7c2ed0f7595d7817666a157" 2641 | 2642 | [[package]] 2643 | name = "robots" 2644 | version = "0.1.0" 2645 | dependencies = [ 2646 | "bevy", 2647 | "bevy_prototype_lyon", 2648 | "byteorder", 2649 | "clap", 2650 | "crossbeam-channel", 2651 | "itertools", 2652 | "lazy_static", 2653 | "rand", 2654 | "serde", 2655 | "serde_json", 2656 | "thiserror", 2657 | "tracing", 2658 | "tracing-subscriber", 2659 | "tracing-tree", 2660 | ] 2661 | 2662 | [[package]] 2663 | name = "rodio" 2664 | version = "0.15.0" 2665 | source = "registry+https://github.com/rust-lang/crates.io-index" 2666 | checksum = "ec0939e9f626e6c6f1989adb6226a039c855ca483053f0ee7c98b90e41cf731e" 2667 | dependencies = [ 2668 | "cpal", 2669 | "lewton", 2670 | ] 2671 | 2672 | [[package]] 2673 | name = "ron" 2674 | version = "0.7.0" 2675 | source = "registry+https://github.com/rust-lang/crates.io-index" 2676 | checksum = "1b861ecaade43ac97886a512b360d01d66be9f41f3c61088b42cedf92e03d678" 2677 | dependencies = [ 2678 | "base64", 2679 | "bitflags", 2680 | "serde", 2681 | ] 2682 | 2683 | [[package]] 2684 | name = "rustc-hash" 2685 | version = "1.1.0" 2686 | source = "registry+https://github.com/rust-lang/crates.io-index" 2687 | checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" 2688 | 2689 | [[package]] 2690 | name = "rustc_version" 2691 | version = "0.2.3" 2692 | source = "registry+https://github.com/rust-lang/crates.io-index" 2693 | checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" 2694 | dependencies = [ 2695 | "semver", 2696 | ] 2697 | 2698 | [[package]] 2699 | name = "rusty-xinput" 2700 | version = "1.2.0" 2701 | source = "registry+https://github.com/rust-lang/crates.io-index" 2702 | checksum = "d2aa654bc32eb9ca14cce1a084abc9dfe43949a4547c35269a094c39272db3bb" 2703 | dependencies = [ 2704 | "lazy_static", 2705 | "log", 2706 | "winapi", 2707 | ] 2708 | 2709 | [[package]] 2710 | name = "ryu" 2711 | version = "1.0.9" 2712 | source = "registry+https://github.com/rust-lang/crates.io-index" 2713 | checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" 2714 | 2715 | [[package]] 2716 | name = "same-file" 2717 | version = "1.0.6" 2718 | source = "registry+https://github.com/rust-lang/crates.io-index" 2719 | checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" 2720 | dependencies = [ 2721 | "winapi-util", 2722 | ] 2723 | 2724 | [[package]] 2725 | name = "scoped_threadpool" 2726 | version = "0.1.9" 2727 | source = "registry+https://github.com/rust-lang/crates.io-index" 2728 | checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" 2729 | 2730 | [[package]] 2731 | name = "scopeguard" 2732 | version = "1.1.0" 2733 | source = "registry+https://github.com/rust-lang/crates.io-index" 2734 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 2735 | 2736 | [[package]] 2737 | name = "semver" 2738 | version = "0.9.0" 2739 | source = "registry+https://github.com/rust-lang/crates.io-index" 2740 | checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" 2741 | dependencies = [ 2742 | "semver-parser", 2743 | ] 2744 | 2745 | [[package]] 2746 | name = "semver-parser" 2747 | version = "0.7.0" 2748 | source = "registry+https://github.com/rust-lang/crates.io-index" 2749 | checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" 2750 | 2751 | [[package]] 2752 | name = "serde" 2753 | version = "1.0.136" 2754 | source = "registry+https://github.com/rust-lang/crates.io-index" 2755 | checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" 2756 | dependencies = [ 2757 | "serde_derive", 2758 | ] 2759 | 2760 | [[package]] 2761 | name = "serde_derive" 2762 | version = "1.0.136" 2763 | source = "registry+https://github.com/rust-lang/crates.io-index" 2764 | checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" 2765 | dependencies = [ 2766 | "proc-macro2", 2767 | "quote", 2768 | "syn", 2769 | ] 2770 | 2771 | [[package]] 2772 | name = "serde_json" 2773 | version = "1.0.79" 2774 | source = "registry+https://github.com/rust-lang/crates.io-index" 2775 | checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95" 2776 | dependencies = [ 2777 | "itoa", 2778 | "ryu", 2779 | "serde", 2780 | ] 2781 | 2782 | [[package]] 2783 | name = "sha1" 2784 | version = "0.6.1" 2785 | source = "registry+https://github.com/rust-lang/crates.io-index" 2786 | checksum = "c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770" 2787 | dependencies = [ 2788 | "sha1_smol", 2789 | ] 2790 | 2791 | [[package]] 2792 | name = "sha1_smol" 2793 | version = "1.0.0" 2794 | source = "registry+https://github.com/rust-lang/crates.io-index" 2795 | checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" 2796 | 2797 | [[package]] 2798 | name = "sharded-slab" 2799 | version = "0.1.4" 2800 | source = "registry+https://github.com/rust-lang/crates.io-index" 2801 | checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" 2802 | dependencies = [ 2803 | "lazy_static", 2804 | ] 2805 | 2806 | [[package]] 2807 | name = "shlex" 2808 | version = "0.1.1" 2809 | source = "registry+https://github.com/rust-lang/crates.io-index" 2810 | checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" 2811 | 2812 | [[package]] 2813 | name = "siphasher" 2814 | version = "0.2.3" 2815 | source = "registry+https://github.com/rust-lang/crates.io-index" 2816 | checksum = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" 2817 | 2818 | [[package]] 2819 | name = "slab" 2820 | version = "0.4.6" 2821 | source = "registry+https://github.com/rust-lang/crates.io-index" 2822 | checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" 2823 | 2824 | [[package]] 2825 | name = "slotmap" 2826 | version = "1.0.6" 2827 | source = "registry+https://github.com/rust-lang/crates.io-index" 2828 | checksum = "e1e08e261d0e8f5c43123b7adf3e4ca1690d655377ac93a03b2c9d3e98de1342" 2829 | dependencies = [ 2830 | "version_check", 2831 | ] 2832 | 2833 | [[package]] 2834 | name = "smallvec" 2835 | version = "1.8.0" 2836 | source = "registry+https://github.com/rust-lang/crates.io-index" 2837 | checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" 2838 | dependencies = [ 2839 | "serde", 2840 | ] 2841 | 2842 | [[package]] 2843 | name = "spirv" 2844 | version = "0.2.0+1.5.4" 2845 | source = "registry+https://github.com/rust-lang/crates.io-index" 2846 | checksum = "246bfa38fe3db3f1dfc8ca5a2cdeb7348c78be2112740cc0ec8ef18b6d94f830" 2847 | dependencies = [ 2848 | "bitflags", 2849 | "num-traits", 2850 | ] 2851 | 2852 | [[package]] 2853 | name = "stdweb" 2854 | version = "0.1.3" 2855 | source = "registry+https://github.com/rust-lang/crates.io-index" 2856 | checksum = "ef5430c8e36b713e13b48a9f709cc21e046723fe44ce34587b73a830203b533e" 2857 | 2858 | [[package]] 2859 | name = "stdweb" 2860 | version = "0.4.20" 2861 | source = "registry+https://github.com/rust-lang/crates.io-index" 2862 | checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5" 2863 | dependencies = [ 2864 | "discard", 2865 | "rustc_version", 2866 | "serde", 2867 | "serde_json", 2868 | "stdweb-derive", 2869 | "stdweb-internal-macros", 2870 | "stdweb-internal-runtime", 2871 | "wasm-bindgen", 2872 | ] 2873 | 2874 | [[package]] 2875 | name = "stdweb-derive" 2876 | version = "0.5.3" 2877 | source = "registry+https://github.com/rust-lang/crates.io-index" 2878 | checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef" 2879 | dependencies = [ 2880 | "proc-macro2", 2881 | "quote", 2882 | "serde", 2883 | "serde_derive", 2884 | "syn", 2885 | ] 2886 | 2887 | [[package]] 2888 | name = "stdweb-internal-macros" 2889 | version = "0.2.9" 2890 | source = "registry+https://github.com/rust-lang/crates.io-index" 2891 | checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11" 2892 | dependencies = [ 2893 | "base-x", 2894 | "proc-macro2", 2895 | "quote", 2896 | "serde", 2897 | "serde_derive", 2898 | "serde_json", 2899 | "sha1", 2900 | "syn", 2901 | ] 2902 | 2903 | [[package]] 2904 | name = "stdweb-internal-runtime" 2905 | version = "0.1.5" 2906 | source = "registry+https://github.com/rust-lang/crates.io-index" 2907 | checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" 2908 | 2909 | [[package]] 2910 | name = "stretch" 2911 | version = "0.3.2" 2912 | source = "registry+https://github.com/rust-lang/crates.io-index" 2913 | checksum = "7b0dc6d20ce137f302edf90f9cd3d278866fd7fb139efca6f246161222ad6d87" 2914 | dependencies = [ 2915 | "lazy_static", 2916 | "libm", 2917 | ] 2918 | 2919 | [[package]] 2920 | name = "strsim" 2921 | version = "0.10.0" 2922 | source = "registry+https://github.com/rust-lang/crates.io-index" 2923 | checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" 2924 | 2925 | [[package]] 2926 | name = "svg_fmt" 2927 | version = "0.4.1" 2928 | source = "registry+https://github.com/rust-lang/crates.io-index" 2929 | checksum = "8fb1df15f412ee2e9dfc1c504260fa695c1c3f10fe9f4a6ee2d2184d7d6450e2" 2930 | 2931 | [[package]] 2932 | name = "svgtypes" 2933 | version = "0.5.0" 2934 | source = "registry+https://github.com/rust-lang/crates.io-index" 2935 | checksum = "9c536faaff1a10837cfe373142583f6e27d81e96beba339147e77b67c9f260ff" 2936 | dependencies = [ 2937 | "float-cmp", 2938 | "siphasher", 2939 | ] 2940 | 2941 | [[package]] 2942 | name = "syn" 2943 | version = "1.0.91" 2944 | source = "registry+https://github.com/rust-lang/crates.io-index" 2945 | checksum = "b683b2b825c8eef438b77c36a06dc262294da3d5a5813fac20da149241dcd44d" 2946 | dependencies = [ 2947 | "proc-macro2", 2948 | "quote", 2949 | "unicode-xid", 2950 | ] 2951 | 2952 | [[package]] 2953 | name = "termcolor" 2954 | version = "1.1.3" 2955 | source = "registry+https://github.com/rust-lang/crates.io-index" 2956 | checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" 2957 | dependencies = [ 2958 | "winapi-util", 2959 | ] 2960 | 2961 | [[package]] 2962 | name = "textwrap" 2963 | version = "0.15.0" 2964 | source = "registry+https://github.com/rust-lang/crates.io-index" 2965 | checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" 2966 | 2967 | [[package]] 2968 | name = "thiserror" 2969 | version = "1.0.30" 2970 | source = "registry+https://github.com/rust-lang/crates.io-index" 2971 | checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" 2972 | dependencies = [ 2973 | "thiserror-impl", 2974 | ] 2975 | 2976 | [[package]] 2977 | name = "thiserror-impl" 2978 | version = "1.0.30" 2979 | source = "registry+https://github.com/rust-lang/crates.io-index" 2980 | checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" 2981 | dependencies = [ 2982 | "proc-macro2", 2983 | "quote", 2984 | "syn", 2985 | ] 2986 | 2987 | [[package]] 2988 | name = "thread_local" 2989 | version = "1.1.4" 2990 | source = "registry+https://github.com/rust-lang/crates.io-index" 2991 | checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" 2992 | dependencies = [ 2993 | "once_cell", 2994 | ] 2995 | 2996 | [[package]] 2997 | name = "tinyvec" 2998 | version = "1.5.1" 2999 | source = "registry+https://github.com/rust-lang/crates.io-index" 3000 | checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" 3001 | dependencies = [ 3002 | "tinyvec_macros", 3003 | ] 3004 | 3005 | [[package]] 3006 | name = "tinyvec_macros" 3007 | version = "0.1.0" 3008 | source = "registry+https://github.com/rust-lang/crates.io-index" 3009 | checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" 3010 | 3011 | [[package]] 3012 | name = "toml" 3013 | version = "0.5.9" 3014 | source = "registry+https://github.com/rust-lang/crates.io-index" 3015 | checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" 3016 | dependencies = [ 3017 | "indexmap", 3018 | "serde", 3019 | ] 3020 | 3021 | [[package]] 3022 | name = "tracing" 3023 | version = "0.1.34" 3024 | source = "registry+https://github.com/rust-lang/crates.io-index" 3025 | checksum = "5d0ecdcb44a79f0fe9844f0c4f33a342cbcbb5117de8001e6ba0dc2351327d09" 3026 | dependencies = [ 3027 | "cfg-if 1.0.0", 3028 | "pin-project-lite", 3029 | "tracing-attributes", 3030 | "tracing-core", 3031 | ] 3032 | 3033 | [[package]] 3034 | name = "tracing-attributes" 3035 | version = "0.1.20" 3036 | source = "registry+https://github.com/rust-lang/crates.io-index" 3037 | checksum = "2e65ce065b4b5c53e73bb28912318cb8c9e9ad3921f1d669eb0e68b4c8143a2b" 3038 | dependencies = [ 3039 | "proc-macro2", 3040 | "quote", 3041 | "syn", 3042 | ] 3043 | 3044 | [[package]] 3045 | name = "tracing-core" 3046 | version = "0.1.26" 3047 | source = "registry+https://github.com/rust-lang/crates.io-index" 3048 | checksum = "f54c8ca710e81886d498c2fd3331b56c93aa248d49de2222ad2742247c60072f" 3049 | dependencies = [ 3050 | "lazy_static", 3051 | "valuable", 3052 | ] 3053 | 3054 | [[package]] 3055 | name = "tracing-log" 3056 | version = "0.1.2" 3057 | source = "registry+https://github.com/rust-lang/crates.io-index" 3058 | checksum = "a6923477a48e41c1951f1999ef8bb5a3023eb723ceadafe78ffb65dc366761e3" 3059 | dependencies = [ 3060 | "lazy_static", 3061 | "log", 3062 | "tracing-core", 3063 | ] 3064 | 3065 | [[package]] 3066 | name = "tracing-subscriber" 3067 | version = "0.3.11" 3068 | source = "registry+https://github.com/rust-lang/crates.io-index" 3069 | checksum = "4bc28f93baff38037f64e6f43d34cfa1605f27a49c34e8a04c5e78b0babf2596" 3070 | dependencies = [ 3071 | "ansi_term", 3072 | "lazy_static", 3073 | "matchers", 3074 | "regex", 3075 | "sharded-slab", 3076 | "smallvec", 3077 | "thread_local", 3078 | "tracing", 3079 | "tracing-core", 3080 | "tracing-log", 3081 | ] 3082 | 3083 | [[package]] 3084 | name = "tracing-tree" 3085 | version = "0.2.0" 3086 | source = "registry+https://github.com/rust-lang/crates.io-index" 3087 | checksum = "3ce989c9962c7f61fe084dd4a230eec784649dfc2392467c790007c3a6e134e7" 3088 | dependencies = [ 3089 | "ansi_term", 3090 | "atty", 3091 | "tracing-core", 3092 | "tracing-log", 3093 | "tracing-subscriber", 3094 | ] 3095 | 3096 | [[package]] 3097 | name = "tracing-wasm" 3098 | version = "0.2.1" 3099 | source = "registry+https://github.com/rust-lang/crates.io-index" 3100 | checksum = "4575c663a174420fa2d78f4108ff68f65bf2fbb7dd89f33749b6e826b3626e07" 3101 | dependencies = [ 3102 | "tracing", 3103 | "tracing-subscriber", 3104 | "wasm-bindgen", 3105 | ] 3106 | 3107 | [[package]] 3108 | name = "ttf-parser" 3109 | version = "0.15.0" 3110 | source = "registry+https://github.com/rust-lang/crates.io-index" 3111 | checksum = "c74c96594835e10fa545e2a51e8709f30b173a092bfd6036ef2cec53376244f3" 3112 | 3113 | [[package]] 3114 | name = "unicode-width" 3115 | version = "0.1.9" 3116 | source = "registry+https://github.com/rust-lang/crates.io-index" 3117 | checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" 3118 | 3119 | [[package]] 3120 | name = "unicode-xid" 3121 | version = "0.2.2" 3122 | source = "registry+https://github.com/rust-lang/crates.io-index" 3123 | checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" 3124 | 3125 | [[package]] 3126 | name = "uuid" 3127 | version = "0.8.2" 3128 | source = "registry+https://github.com/rust-lang/crates.io-index" 3129 | checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" 3130 | dependencies = [ 3131 | "getrandom", 3132 | "serde", 3133 | ] 3134 | 3135 | [[package]] 3136 | name = "valuable" 3137 | version = "0.1.0" 3138 | source = "registry+https://github.com/rust-lang/crates.io-index" 3139 | checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" 3140 | 3141 | [[package]] 3142 | name = "vec_map" 3143 | version = "0.8.2" 3144 | source = "registry+https://github.com/rust-lang/crates.io-index" 3145 | checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" 3146 | 3147 | [[package]] 3148 | name = "version_check" 3149 | version = "0.9.4" 3150 | source = "registry+https://github.com/rust-lang/crates.io-index" 3151 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 3152 | 3153 | [[package]] 3154 | name = "waker-fn" 3155 | version = "1.1.0" 3156 | source = "registry+https://github.com/rust-lang/crates.io-index" 3157 | checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" 3158 | 3159 | [[package]] 3160 | name = "walkdir" 3161 | version = "2.3.2" 3162 | source = "registry+https://github.com/rust-lang/crates.io-index" 3163 | checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" 3164 | dependencies = [ 3165 | "same-file", 3166 | "winapi", 3167 | "winapi-util", 3168 | ] 3169 | 3170 | [[package]] 3171 | name = "wasi" 3172 | version = "0.10.2+wasi-snapshot-preview1" 3173 | source = "registry+https://github.com/rust-lang/crates.io-index" 3174 | checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" 3175 | 3176 | [[package]] 3177 | name = "wasi" 3178 | version = "0.11.0+wasi-snapshot-preview1" 3179 | source = "registry+https://github.com/rust-lang/crates.io-index" 3180 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 3181 | 3182 | [[package]] 3183 | name = "wasm-bindgen" 3184 | version = "0.2.80" 3185 | source = "registry+https://github.com/rust-lang/crates.io-index" 3186 | checksum = "27370197c907c55e3f1a9fbe26f44e937fe6451368324e009cba39e139dc08ad" 3187 | dependencies = [ 3188 | "cfg-if 1.0.0", 3189 | "wasm-bindgen-macro", 3190 | ] 3191 | 3192 | [[package]] 3193 | name = "wasm-bindgen-backend" 3194 | version = "0.2.80" 3195 | source = "registry+https://github.com/rust-lang/crates.io-index" 3196 | checksum = "53e04185bfa3a779273da532f5025e33398409573f348985af9a1cbf3774d3f4" 3197 | dependencies = [ 3198 | "bumpalo", 3199 | "lazy_static", 3200 | "log", 3201 | "proc-macro2", 3202 | "quote", 3203 | "syn", 3204 | "wasm-bindgen-shared", 3205 | ] 3206 | 3207 | [[package]] 3208 | name = "wasm-bindgen-futures" 3209 | version = "0.4.30" 3210 | source = "registry+https://github.com/rust-lang/crates.io-index" 3211 | checksum = "6f741de44b75e14c35df886aff5f1eb73aa114fa5d4d00dcd37b5e01259bf3b2" 3212 | dependencies = [ 3213 | "cfg-if 1.0.0", 3214 | "js-sys", 3215 | "wasm-bindgen", 3216 | "web-sys", 3217 | ] 3218 | 3219 | [[package]] 3220 | name = "wasm-bindgen-macro" 3221 | version = "0.2.80" 3222 | source = "registry+https://github.com/rust-lang/crates.io-index" 3223 | checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5" 3224 | dependencies = [ 3225 | "quote", 3226 | "wasm-bindgen-macro-support", 3227 | ] 3228 | 3229 | [[package]] 3230 | name = "wasm-bindgen-macro-support" 3231 | version = "0.2.80" 3232 | source = "registry+https://github.com/rust-lang/crates.io-index" 3233 | checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b" 3234 | dependencies = [ 3235 | "proc-macro2", 3236 | "quote", 3237 | "syn", 3238 | "wasm-bindgen-backend", 3239 | "wasm-bindgen-shared", 3240 | ] 3241 | 3242 | [[package]] 3243 | name = "wasm-bindgen-shared" 3244 | version = "0.2.80" 3245 | source = "registry+https://github.com/rust-lang/crates.io-index" 3246 | checksum = "d554b7f530dee5964d9a9468d95c1f8b8acae4f282807e7d27d4b03099a46744" 3247 | 3248 | [[package]] 3249 | name = "web-sys" 3250 | version = "0.3.57" 3251 | source = "registry+https://github.com/rust-lang/crates.io-index" 3252 | checksum = "7b17e741662c70c8bd24ac5c5b18de314a2c26c32bf8346ee1e6f53de919c283" 3253 | dependencies = [ 3254 | "js-sys", 3255 | "wasm-bindgen", 3256 | ] 3257 | 3258 | [[package]] 3259 | name = "wgpu" 3260 | version = "0.12.0" 3261 | source = "registry+https://github.com/rust-lang/crates.io-index" 3262 | checksum = "b97cd781ff044d6d697b632a2e212032c2e957d1afaa21dbf58069cbb8f78567" 3263 | dependencies = [ 3264 | "arrayvec 0.7.2", 3265 | "js-sys", 3266 | "log", 3267 | "naga", 3268 | "parking_lot", 3269 | "raw-window-handle", 3270 | "smallvec", 3271 | "wasm-bindgen", 3272 | "wasm-bindgen-futures", 3273 | "web-sys", 3274 | "wgpu-core", 3275 | "wgpu-hal", 3276 | "wgpu-types", 3277 | ] 3278 | 3279 | [[package]] 3280 | name = "wgpu-core" 3281 | version = "0.12.2" 3282 | source = "registry+https://github.com/rust-lang/crates.io-index" 3283 | checksum = "c4688c000eb841ca55f7b35db659b78d6e1cd77d7caf8fb929f4e181f754047d" 3284 | dependencies = [ 3285 | "arrayvec 0.7.2", 3286 | "bitflags", 3287 | "cfg_aliases", 3288 | "codespan-reporting", 3289 | "copyless", 3290 | "fxhash", 3291 | "log", 3292 | "naga", 3293 | "parking_lot", 3294 | "profiling", 3295 | "raw-window-handle", 3296 | "smallvec", 3297 | "thiserror", 3298 | "wgpu-hal", 3299 | "wgpu-types", 3300 | ] 3301 | 3302 | [[package]] 3303 | name = "wgpu-hal" 3304 | version = "0.12.4" 3305 | source = "registry+https://github.com/rust-lang/crates.io-index" 3306 | checksum = "93b1a9400e8d7f32dd4dd909bb9a391015d70633d639775ddd3f14d1104bc970" 3307 | dependencies = [ 3308 | "arrayvec 0.7.2", 3309 | "ash", 3310 | "bit-set", 3311 | "bitflags", 3312 | "block", 3313 | "core-graphics-types", 3314 | "d3d12", 3315 | "foreign-types", 3316 | "fxhash", 3317 | "glow", 3318 | "gpu-alloc", 3319 | "gpu-descriptor", 3320 | "inplace_it", 3321 | "js-sys", 3322 | "khronos-egl", 3323 | "libloading", 3324 | "log", 3325 | "metal", 3326 | "naga", 3327 | "objc", 3328 | "parking_lot", 3329 | "profiling", 3330 | "range-alloc", 3331 | "raw-window-handle", 3332 | "renderdoc-sys", 3333 | "thiserror", 3334 | "wasm-bindgen", 3335 | "web-sys", 3336 | "wgpu-types", 3337 | "winapi", 3338 | ] 3339 | 3340 | [[package]] 3341 | name = "wgpu-types" 3342 | version = "0.12.0" 3343 | source = "registry+https://github.com/rust-lang/crates.io-index" 3344 | checksum = "549533d9e1cdd4b4cda7718d33ff500fc4c34b5467b71d76b547ae0324f3b2a2" 3345 | dependencies = [ 3346 | "bitflags", 3347 | ] 3348 | 3349 | [[package]] 3350 | name = "winapi" 3351 | version = "0.3.9" 3352 | source = "registry+https://github.com/rust-lang/crates.io-index" 3353 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 3354 | dependencies = [ 3355 | "winapi-i686-pc-windows-gnu", 3356 | "winapi-x86_64-pc-windows-gnu", 3357 | ] 3358 | 3359 | [[package]] 3360 | name = "winapi-i686-pc-windows-gnu" 3361 | version = "0.4.0" 3362 | source = "registry+https://github.com/rust-lang/crates.io-index" 3363 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 3364 | 3365 | [[package]] 3366 | name = "winapi-util" 3367 | version = "0.1.5" 3368 | source = "registry+https://github.com/rust-lang/crates.io-index" 3369 | checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" 3370 | dependencies = [ 3371 | "winapi", 3372 | ] 3373 | 3374 | [[package]] 3375 | name = "winapi-x86_64-pc-windows-gnu" 3376 | version = "0.4.0" 3377 | source = "registry+https://github.com/rust-lang/crates.io-index" 3378 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 3379 | 3380 | [[package]] 3381 | name = "winit" 3382 | version = "0.26.1" 3383 | source = "registry+https://github.com/rust-lang/crates.io-index" 3384 | checksum = "9b43cc931d58b99461188607efd7acb2a093e65fc621f54cad78517a6063e73a" 3385 | dependencies = [ 3386 | "bitflags", 3387 | "cocoa", 3388 | "core-foundation 0.9.3", 3389 | "core-graphics 0.22.3", 3390 | "core-video-sys", 3391 | "dispatch", 3392 | "instant", 3393 | "lazy_static", 3394 | "libc", 3395 | "log", 3396 | "mio 0.8.2", 3397 | "ndk 0.5.0", 3398 | "ndk-glue 0.5.1", 3399 | "ndk-sys 0.2.2", 3400 | "objc", 3401 | "parking_lot", 3402 | "percent-encoding", 3403 | "raw-window-handle", 3404 | "wasm-bindgen", 3405 | "web-sys", 3406 | "winapi", 3407 | "x11-dl", 3408 | ] 3409 | 3410 | [[package]] 3411 | name = "x11-dl" 3412 | version = "2.19.1" 3413 | source = "registry+https://github.com/rust-lang/crates.io-index" 3414 | checksum = "ea26926b4ce81a6f5d9d0f3a0bc401e5a37c6ae14a1bfaa8ff6099ca80038c59" 3415 | dependencies = [ 3416 | "lazy_static", 3417 | "libc", 3418 | "pkg-config", 3419 | ] 3420 | 3421 | [[package]] 3422 | name = "xi-unicode" 3423 | version = "0.3.0" 3424 | source = "registry+https://github.com/rust-lang/crates.io-index" 3425 | checksum = "a67300977d3dc3f8034dae89778f502b6ba20b269527b3223ba59c0cf393bb8a" 3426 | --------------------------------------------------------------------------------