Compare commits
10 commits
104b912456
...
f969a9fc21
Author | SHA1 | Date | |
---|---|---|---|
![]() |
f969a9fc21 | ||
![]() |
d001bacae8 | ||
![]() |
a085ae78bb | ||
![]() |
ea80597050 | ||
![]() |
f66600cabc | ||
![]() |
abfc03434c | ||
![]() |
ed8fbcf70c | ||
![]() |
24e9621194 | ||
![]() |
ebaa596a2d | ||
![]() |
cf4f15f509 |
15 changed files with 634 additions and 28 deletions
248
Cargo.lock
generated
248
Cargo.lock
generated
|
@ -72,6 +72,17 @@ version = "1.0.95"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04"
|
||||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
version = "0.1.85"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f934833b4b7233644e5848f235df3f57ed8c80f1528a26c3dfa13d2147fa056"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.4.0"
|
||||
|
@ -99,6 +110,15 @@ version = "2.6.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.16.0"
|
||||
|
@ -130,6 +150,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -144,6 +165,18 @@ dependencies = [
|
|||
"strsim",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.5.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.7.4"
|
||||
|
@ -156,16 +189,55 @@ version = "1.0.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"crypto-common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "durak-frthistime"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
"rand",
|
||||
"petname",
|
||||
"rand 0.9.0-beta.1",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha256",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.10"
|
||||
|
@ -176,6 +248,27 @@ dependencies = [
|
|||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.3.0-rc.0"
|
||||
|
@ -197,12 +290,39 @@ version = "0.31.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||
|
||||
[[package]]
|
||||
name = "hex"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||
|
||||
[[package]]
|
||||
name = "is_terminal_polyfill"
|
||||
version = "1.70.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.76"
|
||||
|
@ -305,6 +425,20 @@ dependencies = [
|
|||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "petname"
|
||||
version = "2.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9cd31dcfdbbd7431a807ef4df6edd6473228e94d5c805e8cf671227a21bad068"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
"itertools",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rand 0.8.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.16"
|
||||
|
@ -338,17 +472,38 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha 0.3.1",
|
||||
"rand_core 0.6.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.9.0-beta.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c8478de76992f2825a1052cc2ae9d1401cdb62687761d4100ddd69a73dc3dc48"
|
||||
dependencies = [
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
"rand_chacha 0.9.0-beta.1",
|
||||
"rand_core 0.9.0-beta.1",
|
||||
"zerocopy 0.8.14",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core 0.6.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.9.0-beta.1"
|
||||
|
@ -356,7 +511,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "f16da77124f4ee9fabd55ce6540866e9101431863b4876de58b68797f331adf2"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
"rand_core 0.9.0-beta.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom 0.2.15",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -365,7 +529,7 @@ version = "0.9.0-beta.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a98fa0b8309344136abe6244130311e76997e546f76fae8054422a7539b43df7"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"getrandom 0.3.0-rc.0",
|
||||
"zerocopy 0.8.14",
|
||||
]
|
||||
|
||||
|
@ -397,12 +561,74 @@ dependencies = [
|
|||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.217"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.217"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.135"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b0d7ba2887406110130a978386c4e1befb98c674b4fba677954e4db976630d9"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"memchr",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.10.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha256"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "18278f6a914fa3070aa316493f7d2ddfb9ac86ebc06fa3b83bffda487e9065b0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"bytes",
|
||||
"hex",
|
||||
"sha2",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook-registry"
|
||||
version = "1.4.2"
|
||||
|
@ -474,6 +700,12 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.14"
|
||||
|
@ -486,6 +718,12 @@ version = "0.2.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
|
|
17
Cargo.toml
17
Cargo.toml
|
@ -3,8 +3,25 @@ name = "durak-frthistime"
|
|||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
name = "lib"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "server"
|
||||
path = "src/bin/server.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "client"
|
||||
path = "src/bin/client.rs"
|
||||
|
||||
[dependencies]
|
||||
rand = "0.9.0-beta.1"
|
||||
clap = "4.5.23"
|
||||
tokio = { version = "1.42.0", features = ["full"] }
|
||||
anyhow = "1.0.95"
|
||||
serde_json = "1.0.135"
|
||||
serde = { version = "1.0.217", features = ["derive"] }
|
||||
sha256 = "1.5.0"
|
||||
petname = "2.0.2"
|
||||
crossterm = "0.28.1"
|
||||
|
|
15
src/bin/client.rs
Normal file
15
src/bin/client.rs
Normal file
|
@ -0,0 +1,15 @@
|
|||
use lib::{client::Client, message::Message};
|
||||
|
||||
#[tokio::main]
|
||||
pub async fn main() -> anyhow::Result<()> {
|
||||
let mut client = Client::connect("127.0.0.1", 8080).await?;
|
||||
|
||||
for i in 1..11 {
|
||||
let message = Message::new(format!("Hello toto x {}!!!", i));
|
||||
client.send_message(message.unwrap().clone()).await?;
|
||||
}
|
||||
|
||||
client.send_message(Message::new("EXIT").unwrap()).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
8
src/bin/server.rs
Normal file
8
src/bin/server.rs
Normal file
|
@ -0,0 +1,8 @@
|
|||
use lib::server::Server;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
let mut server = Server::new("127.0.0.1", 8080);
|
||||
server.run().await?;
|
||||
Ok(())
|
||||
}
|
29
src/card.rs
29
src/card.rs
|
@ -1,10 +1,14 @@
|
|||
#[derive(Debug)]
|
||||
use std::fmt::Display;
|
||||
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, PartialEq, Eq, Hash, Clone)]
|
||||
pub struct Card {
|
||||
pub suit: Suit,
|
||||
pub value: u8,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[derive(Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash)]
|
||||
pub enum Suit {
|
||||
Hearts,
|
||||
Diamonds,
|
||||
|
@ -13,7 +17,7 @@ pub enum Suit {
|
|||
}
|
||||
|
||||
impl Card {
|
||||
pub fn new(suit: Suit, value: u8) -> Card {
|
||||
pub fn new(suit: Suit, value: u8) -> Self {
|
||||
Card {
|
||||
suit,
|
||||
value,
|
||||
|
@ -28,3 +32,22 @@ impl Card {
|
|||
self.value
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Suit {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let suit = match self {
|
||||
Suit::Diamonds => String::from("♦"),
|
||||
Suit::Hearts => String::from("♥"),
|
||||
Suit::Spades => String::from("♠"),
|
||||
Suit::Clubs => String::from("♣"),
|
||||
};
|
||||
|
||||
write!(f, "{}", suit)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Card {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "[{}{}]", self.value, self.suit)
|
||||
}
|
||||
}
|
||||
|
|
28
src/client.rs
Normal file
28
src/client.rs
Normal file
|
@ -0,0 +1,28 @@
|
|||
use tokio::{io::AsyncWriteExt, net::TcpStream};
|
||||
|
||||
use crate::message::Message;
|
||||
|
||||
pub struct Client {
|
||||
pub server_host: String,
|
||||
pub server_port: u16,
|
||||
pub stream: TcpStream,
|
||||
}
|
||||
|
||||
impl Client {
|
||||
pub async fn connect(host: impl Into<String>, port: u16) -> anyhow::Result<Self> {
|
||||
let host = host.into();
|
||||
let address = format!("{}:{}", host, port);
|
||||
let stream = TcpStream::connect(address).await?;
|
||||
|
||||
Ok(Self {
|
||||
server_host: host,
|
||||
server_port: port,
|
||||
stream,
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn send_message(&mut self, message: Message) -> anyhow::Result<()> {
|
||||
self.stream.write_all(&message.encode()).await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
5
src/constant.rs
Normal file
5
src/constant.rs
Normal file
|
@ -0,0 +1,5 @@
|
|||
pub const METADATA_SIZE: usize = 2;
|
||||
pub const MESSAGE_KIND_MOVE: u8 = 0;
|
||||
pub const MESSAGE_KIND_PLAYER_SETUP: u8 = 1;
|
||||
pub const MESSAGE_KIND_LOBBY_SETUP: u8 = 2;
|
||||
|
25
src/deck.rs
25
src/deck.rs
|
@ -1,15 +1,16 @@
|
|||
use crate::card::Card;
|
||||
use crate::card::Suit;
|
||||
|
||||
use rand::seq::SliceRandom;
|
||||
use rand::rng;
|
||||
|
||||
use crate::card::Card;
|
||||
use crate::card::Suit;
|
||||
|
||||
#[derive(PartialEq, Eq, Hash, Clone)]
|
||||
pub struct Deck {
|
||||
pub deck: Vec<Card>,
|
||||
}
|
||||
|
||||
impl Deck {
|
||||
pub fn new() -> Deck {
|
||||
pub fn new() -> Self {
|
||||
// possible values go from 0 to 8 because Durak is played
|
||||
// without cards with a value lower than 6 in real life
|
||||
// and ace is the highest card
|
||||
|
@ -34,14 +35,24 @@ impl Deck {
|
|||
self.deck
|
||||
}
|
||||
|
||||
pub fn shuffle(mut self) -> Deck {
|
||||
pub fn shuffle(mut self) -> Self {
|
||||
let mut rng = rng();
|
||||
self.deck.shuffle(&mut rng); // shuffle modifies in place
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub fn draw(mut self) -> Card {
|
||||
todo!()
|
||||
pub fn draw(mut self, n: u8) -> Vec<Card> {
|
||||
if n as usize > self.deck.len() {
|
||||
let drawn: Vec<Card> = self.deck
|
||||
.drain(0..)
|
||||
.collect();
|
||||
drawn
|
||||
} else {
|
||||
let drawn: Vec<Card> = self.deck
|
||||
.drain(0..n as usize)
|
||||
.collect();
|
||||
drawn
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
9
src/lib.rs
Normal file
9
src/lib.rs
Normal file
|
@ -0,0 +1,9 @@
|
|||
pub mod server;
|
||||
pub mod client;
|
||||
pub mod card;
|
||||
pub mod deck;
|
||||
pub mod lobby;
|
||||
pub mod player;
|
||||
pub mod message;
|
||||
pub mod message_read;
|
||||
pub mod constant;
|
40
src/lobby.rs
Normal file
40
src/lobby.rs
Normal file
|
@ -0,0 +1,40 @@
|
|||
use crate::{deck::Deck, player::Player};
|
||||
use petname::Generator;
|
||||
|
||||
#[derive(Eq, PartialEq, Hash, Clone)]
|
||||
pub struct Lobby {
|
||||
pub id: String,
|
||||
pub players: Vec<Player>,
|
||||
pub deck: Deck,
|
||||
}
|
||||
|
||||
impl Lobby {
|
||||
pub fn new() -> Self {
|
||||
let players: Vec<Player> = Vec::new();
|
||||
let deck = Deck::new().shuffle();
|
||||
|
||||
let petname = petname::Petnames::default().generate_one(2, "-").expect("no words provided");
|
||||
|
||||
Lobby {
|
||||
id: petname,
|
||||
players,
|
||||
deck,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn join_lobby(mut self, player: Player) {
|
||||
self.players.push(player);
|
||||
}
|
||||
|
||||
pub fn get_players(self) -> Vec<Player> {
|
||||
self.players
|
||||
}
|
||||
|
||||
pub fn get_deck(self) -> Deck {
|
||||
self.deck
|
||||
}
|
||||
|
||||
pub fn get_id(&self) -> String {
|
||||
self.id.clone()
|
||||
}
|
||||
}
|
68
src/main.rs
68
src/main.rs
|
@ -1,22 +1,68 @@
|
|||
use std::collections::HashMap;
|
||||
use std::io::{self, Error};
|
||||
use std::net::SocketAddr;
|
||||
|
||||
use lib::lobby::Lobby;
|
||||
use lib::player::Player;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use anyhow::Result;
|
||||
use tokio::io::{AsyncBufReadExt, AsyncReadExt, AsyncWriteExt, BufReader};
|
||||
use tokio::net::{TcpListener, TcpStream};
|
||||
use tokio::io::AsyncWriteExt;
|
||||
|
||||
use deck::Deck;
|
||||
async fn handle_connection(mut stream: TcpStream, addr: SocketAddr) -> (Option<Player>, Option<Lobby>) {
|
||||
let (mut read, mut write) = stream.split();
|
||||
|
||||
mod card;
|
||||
mod deck;
|
||||
mod player;
|
||||
let mut buf = [0; 1024];
|
||||
|
||||
let mut name = String::new();
|
||||
write.write_all(b"provide name\n").await.expect("failed to write to socket");
|
||||
|
||||
let n = match read.read(&mut buf).await {
|
||||
Ok(0) => return (None, None),
|
||||
Ok(n) => n,
|
||||
Err(e) => {
|
||||
eprintln!("failed to read from socket; err: {:?}", e);
|
||||
return (None, None);
|
||||
},
|
||||
};
|
||||
|
||||
name = String::from_utf8_lossy(&buf[0..n]).to_string();
|
||||
|
||||
// if let Err(e) = write.write_all(&buf[0..n]).await {
|
||||
// eprintln!("failed to write to socket; err = {:?}", e);
|
||||
// return (None, None);
|
||||
// }
|
||||
|
||||
let player = Player::new(addr, &name);
|
||||
|
||||
write.write_all(b"your name is\n").await.expect("failed to write to socket");
|
||||
write.write_all(name.as_bytes()).await.expect("failed to write to socket");
|
||||
|
||||
(Some(player), None)
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), anyhow::Error> {
|
||||
let listener = TcpListener::bind("127.0.0.1:6379").await?;
|
||||
async fn main() -> io::Result<()> {
|
||||
let address = "127.0.0.1:8080".to_string();
|
||||
let listener = TcpListener::bind(&address).await?;
|
||||
|
||||
let mut lobbies: Arc<Mutex<HashMap<String, Lobby>>> = Arc::new(Mutex::new(HashMap::new()));
|
||||
|
||||
loop {
|
||||
match listener.accept().await {
|
||||
Ok((_socket, addr)) => println!("new client: {:?}", addr),
|
||||
Err(e) => println!("couldn't get client: {:?}", e),
|
||||
}
|
||||
let (mut stream, addr) = listener.accept().await?;
|
||||
|
||||
println!("new connection from: {}", addr);
|
||||
|
||||
let lobby_player_handle = tokio::spawn(handle_connection(stream, addr));
|
||||
|
||||
let (player, lobby) = lobby_player_handle.await?;
|
||||
|
||||
match lobby {
|
||||
Some(lobby) => lobbies.insert(lobby.get_id(), lobby),
|
||||
None => continue,
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
54
src/message.rs
Normal file
54
src/message.rs
Normal file
|
@ -0,0 +1,54 @@
|
|||
use crate::constant::METADATA_SIZE;
|
||||
|
||||
// everything here needs to be adjusted for the deserialized json
|
||||
//
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Message {
|
||||
pub message_kind: MessageKind,
|
||||
pub length: u16,
|
||||
pub content: String,
|
||||
}
|
||||
|
||||
// idk i just want to layout something, really didn't think much
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum MessageKind {
|
||||
Move(u8),
|
||||
PlayerSetup(u8),
|
||||
LobbySetup(u8),
|
||||
}
|
||||
|
||||
impl Message {
|
||||
pub fn new(content: impl Into<String>) -> anyhow::Result<Self> {
|
||||
let content = content.into();
|
||||
let length = content.len() as u16;
|
||||
|
||||
// add message kind to constructor
|
||||
Ok(Self {
|
||||
length,
|
||||
content,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn encode(&self) -> Vec<u8> {
|
||||
let mut buffer = Vec::new();
|
||||
buffer.extend(&self.length.to_be_bytes());
|
||||
buffer.extend(self.content.as_bytes());
|
||||
|
||||
buffer
|
||||
}
|
||||
|
||||
pub fn decode(buffer: &[u8]) -> anyhow::Result<Self> {
|
||||
if buffer.len() < METADATA_SIZE {
|
||||
return Err(anyhow::anyhow!("Invalid message length"));
|
||||
}
|
||||
|
||||
let length = u16::from_be_bytes([buffer[0], buffer[1]]);
|
||||
let content = String::from_utf8(buffer[2..2 + length as usize].to_vec())?;
|
||||
|
||||
// add message kind to constructor
|
||||
Ok(Self {
|
||||
length,
|
||||
content,
|
||||
})
|
||||
}
|
||||
}
|
42
src/message_read.rs
Normal file
42
src/message_read.rs
Normal file
|
@ -0,0 +1,42 @@
|
|||
// add message kind everywhere is needed
|
||||
use crate::{constant::METADATA_SIZE, message::Message};
|
||||
|
||||
pub struct MessageReader {
|
||||
pub buffer: Vec<u8>,
|
||||
}
|
||||
|
||||
impl MessageReader {
|
||||
pub fn new() -> Self {
|
||||
Self { buffer: Vec::new() }
|
||||
}
|
||||
|
||||
fn can_parse(&self) -> bool {
|
||||
if self.buffer.len() < METADATA_SIZE {
|
||||
return false;
|
||||
}
|
||||
|
||||
let length = u16::from_be_bytes([self.buffer[0], self.buffer[1]]);
|
||||
self.buffer.len() >= METADATA_SIZE + length as usize
|
||||
}
|
||||
|
||||
fn parse_first(&mut self) -> anyhow::Result<Message> {
|
||||
let length = u16::from_be_bytes([self.buffer[0], self.buffer[1]]);
|
||||
let message_length = METADATA_SIZE + length as usize;
|
||||
let message = self.buffer[..message_length].to_vec();
|
||||
self.buffer = self.buffer[message_length..].to_vec();
|
||||
|
||||
Message::decode(&message)
|
||||
}
|
||||
|
||||
pub fn read(&mut self, data: &[u8]) -> anyhow::Result<Vec<Message>> {
|
||||
self.buffer.extend_from_slice(data);
|
||||
let mut data = vec![];
|
||||
|
||||
while self.can_parse() {
|
||||
let message = self.parse_first()?;
|
||||
data.push(message);
|
||||
}
|
||||
|
||||
Ok(data)
|
||||
}
|
||||
}
|
|
@ -1,20 +1,36 @@
|
|||
use std::net::SocketAddr;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sha256::digest;
|
||||
|
||||
use crate::card::Card;
|
||||
|
||||
#[derive(Serialize, Deserialize, Eq, PartialEq, Hash, Clone)]
|
||||
pub struct Player {
|
||||
// addr will change because at this stage i really
|
||||
// don't know what i am doing
|
||||
// it will probably be something like id or playerid
|
||||
// or some other identifier idk
|
||||
pub addr: SocketAddr,
|
||||
// same goes for id because rn it's just the sha256 of
|
||||
// the ip
|
||||
pub id: String,
|
||||
pub name: String,
|
||||
pub hand: Vec<Card>,
|
||||
}
|
||||
|
||||
impl Player {
|
||||
pub fn new(addr: SocketAddr, name: &str) -> Player {
|
||||
todo!()
|
||||
pub fn new(addr: SocketAddr, name: &str) -> Self {
|
||||
let hand_empty: Vec<Card> = Vec::new();
|
||||
|
||||
let to_digest: String = addr.to_string();
|
||||
let id = digest(to_digest);
|
||||
|
||||
Player {
|
||||
addr,
|
||||
id,
|
||||
name: name.to_string(),
|
||||
hand: hand_empty,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_addr(self) -> SocketAddr {
|
||||
|
|
54
src/server.rs
Normal file
54
src/server.rs
Normal file
|
@ -0,0 +1,54 @@
|
|||
use tokio::{io::AsyncReadExt, net::TcpListener};
|
||||
use crate::message_read::MessageReader;
|
||||
|
||||
pub struct Server {
|
||||
pub host: String,
|
||||
pub port: u16,
|
||||
}
|
||||
|
||||
impl Server {
|
||||
pub fn new(host: impl Into<String>, port: u16) -> Self {
|
||||
Server {
|
||||
host: host.into(),
|
||||
port,
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn run(&mut self) -> anyhow::Result<()> {
|
||||
let listener = TcpListener::bind(format!(
|
||||
"{}:{}",
|
||||
self.host,
|
||||
self.port
|
||||
)).await?;
|
||||
|
||||
println!("Server is running on {}:{}", self.host, self.port);
|
||||
|
||||
loop {
|
||||
let (mut socket, addr) = listener.accept().await?;
|
||||
println!("Connection received from {}", addr);
|
||||
|
||||
tokio::task::spawn(async move {
|
||||
let mut message_reader = MessageReader::new();
|
||||
'handler: loop {
|
||||
let mut buffer = vec![0; 256];
|
||||
let bytes_read = socket.read(&mut buffer).await?;
|
||||
|
||||
let messages = message_reader.read(&buffer[..bytes_read])?;
|
||||
|
||||
for message in messages {
|
||||
if message.content == "EXIT" {
|
||||
println!("Connection closed by the client");
|
||||
break 'handler;
|
||||
}
|
||||
|
||||
println!("Message:\n{:?}", message);
|
||||
}
|
||||
}
|
||||
|
||||
Ok::<(), anyhow::Error>(())
|
||||
});
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue