mirror of
https://github.com/pcvolkmer/winelounge.git
synced 2025-04-19 18:36:50 +00:00
Initial changes for multiplayer mode
This commit is contained in:
parent
ccf90b4da7
commit
b59b6d62a7
275
Cargo.lock
generated
275
Cargo.lock
generated
@ -14,6 +14,12 @@ version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
@ -41,7 +47,16 @@ checksum = "418d37c8b1d42553c93648be529cb70f920d3baf8ef469b74b9638df426e0b4c"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
"wasi 0.10.2+wasi-snapshot-preview1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -56,6 +71,63 @@ version = "0.2.118"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06e509672465a0504304aa87f9f176f2b2b716ed8fb105ebe5c02dc6dce96a94"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "52da4364ffb0e4fe33a9841a98a3f3014fb964045ce4f7a45a398243c8d6b0c9"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"miow",
|
||||
"ntapi",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miow"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ntapi"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.44"
|
||||
@ -75,12 +147,75 @@ dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9"
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
"parking_lot_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"smallvec",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.5"
|
||||
@ -111,6 +246,21 @@ dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.2.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
|
||||
[[package]]
|
||||
name = "sdl2"
|
||||
version = "0.35.2"
|
||||
@ -134,6 +284,42 @@ dependencies = [
|
||||
"version-compare",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook-registry"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83"
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ff7c592601f11445996a06f8ad0c27f094a58857c2f89e97974ab9235b92c52"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.1.43"
|
||||
@ -144,6 +330,43 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.18.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dce653fb475565de9f6fb0614b28bca8df2c430c0cf84bcd9c843f15de5414cc"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"libc",
|
||||
"memchr",
|
||||
"mio",
|
||||
"num_cpus",
|
||||
"once_cell",
|
||||
"parking_lot",
|
||||
"pin-project-lite",
|
||||
"signal-hook-registry",
|
||||
"socket2",
|
||||
"tokio-macros",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-macros"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04"
|
||||
|
||||
[[package]]
|
||||
name = "version-compare"
|
||||
version = "0.1.0"
|
||||
@ -156,6 +379,12 @@ version = "0.10.2+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
@ -178,6 +407,49 @@ version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
|
||||
dependencies = [
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.36.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
|
||||
|
||||
[[package]]
|
||||
name = "winelounge"
|
||||
version = "0.1.0"
|
||||
@ -185,4 +457,5 @@ dependencies = [
|
||||
"chrono",
|
||||
"rand",
|
||||
"sdl2",
|
||||
"tokio",
|
||||
]
|
||||
|
@ -3,7 +3,7 @@ name = "winelounge"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
autobins = true
|
||||
|
||||
[dependencies]
|
||||
chrono = "0.4"
|
||||
@ -13,6 +13,11 @@ rand = "0.8"
|
||||
version = "0.35"
|
||||
features = ["image", "ttf"]
|
||||
|
||||
[dependencies.tokio]
|
||||
version = "1.18"
|
||||
features = ["full"]
|
||||
default-features = false
|
||||
|
||||
[profile.release]
|
||||
opt-level = "s"
|
||||
codegen-units = 1
|
||||
|
12
src/bin/winelounge-server/main.rs
Normal file
12
src/bin/winelounge-server/main.rs
Normal file
@ -0,0 +1,12 @@
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
|
||||
let listener = tokio::net::TcpListener::bind(":7888").await.expect("Cannot open socket");
|
||||
|
||||
'listener: loop {
|
||||
|
||||
let (socket, _) = listener.accept().await.expect("Cannot accept connection");
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -11,6 +11,7 @@ use crate::world::World;
|
||||
mod player;
|
||||
mod sprite;
|
||||
mod world;
|
||||
mod net;
|
||||
|
||||
const GLASS_SPACE: u8 = 5;
|
||||
|
||||
@ -40,6 +41,8 @@ fn main() {
|
||||
|
||||
let mut world = World::init();
|
||||
|
||||
world.spawn_player("Test".to_string(), 100, 100);
|
||||
|
||||
'running: loop {
|
||||
for event in event_pump.poll_iter() {
|
||||
match event {
|
||||
|
183
src/net.rs
Normal file
183
src/net.rs
Normal file
@ -0,0 +1,183 @@
|
||||
use crate::world::{BoxAreaContent, BoxAreaPosition, Command, Direction};
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::str::FromStr;
|
||||
|
||||
impl Display for Direction {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Direction::Up => write!(f, "Up"),
|
||||
Direction::Down => write!(f, "Down"),
|
||||
Direction::Left => write!(f, "Left"),
|
||||
Direction::Right => write!(f, "Right"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Direction {
|
||||
type Err = ();
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"Up" => Ok(Direction::Up),
|
||||
"Down" => Ok(Direction::Down),
|
||||
"Left" => Ok(Direction::Left),
|
||||
"Right" => Ok(Direction::Right),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for BoxAreaPosition {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
BoxAreaPosition::RightTop => write!(f, "RightTop"),
|
||||
BoxAreaPosition::RightBottom => write!(f, "RightBottom"),
|
||||
BoxAreaPosition::LeftBottom => write!(f, "LeftBottom"),
|
||||
BoxAreaPosition::LeftTop => write!(f, "LeftTop"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for BoxAreaPosition {
|
||||
type Err = ();
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"RightTop" => Ok(BoxAreaPosition::RightTop),
|
||||
"RightBottom" => Ok(BoxAreaPosition::RightBottom),
|
||||
"LeftBottom" => Ok(BoxAreaPosition::LeftBottom),
|
||||
"LeftTop" => Ok(BoxAreaPosition::LeftTop),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for BoxAreaContent {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
BoxAreaContent::Nothing => write!(f, "Nothing"),
|
||||
BoxAreaContent::HiddenBox => write!(f, "HiddenBox"),
|
||||
BoxAreaContent::EmptyGlass => write!(f, "EmptyGlass"),
|
||||
BoxAreaContent::FilledBottle => write!(f, "FilledBottle"),
|
||||
BoxAreaContent::EmptyBottle => write!(f, "EmptyBottle"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for BoxAreaContent {
|
||||
type Err = ();
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"Nothing" => Ok(BoxAreaContent::Nothing),
|
||||
"HiddenBox" => Ok(BoxAreaContent::HiddenBox),
|
||||
"EmptyGlass" => Ok(BoxAreaContent::EmptyGlass),
|
||||
"FilledBottle" => Ok(BoxAreaContent::FilledBottle),
|
||||
"EmptyBottle" => Ok(BoxAreaContent::EmptyBottle),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Command {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Command::SpawnPlayer(player_id, x, y) => write!(f, "Spawn {}", player_id),
|
||||
Command::RemovePlayer(player_id) => write!(f, "Face {}", player_id),
|
||||
Command::FacePlayer(player_id, direction) => write!(f, "Face {} {}", player_id, direction),
|
||||
Command::MovePlayer(player_id, direction) => write!(f, "Move {} {}", player_id, direction),
|
||||
Command::StopPlayer(player_id) => write!(f, "Stop {}", player_id),
|
||||
Command::UpdateBoxArea(pos, content) => write!(f, "UpdateBoxArea {} {}", pos, content),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Command {
|
||||
type Err = ();
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let mut parts = s.split(' ');
|
||||
|
||||
match parts.next() {
|
||||
Some("Spawn") => match parts.next() {
|
||||
Some(player_id) => match parts.next() {
|
||||
Some(x) => match parts.next() {
|
||||
Some(y) => Ok(Command::SpawnPlayer(player_id.to_string(), x.parse().unwrap(), y.parse().unwrap())),
|
||||
_ => Err(())
|
||||
},
|
||||
_ => Err(())
|
||||
}
|
||||
_ => Err(())
|
||||
},
|
||||
Some("Remove") => match parts.next() {
|
||||
Some(player_id) => Ok(Command::RemovePlayer(player_id.to_string())),
|
||||
_ => Err(())
|
||||
},
|
||||
Some("Face") => match parts.next() {
|
||||
Some(player_id) => match parts.next() {
|
||||
Some(direction) => Ok(Command::FacePlayer(player_id.to_string(), direction.parse::<Direction>().unwrap())),
|
||||
_ => Err(()),
|
||||
},
|
||||
_ => Err(())
|
||||
},
|
||||
Some("Move") => match parts.next() {
|
||||
Some(player_id) => match parts.next() {
|
||||
Some(direction) => Ok(Command::MovePlayer(player_id.to_string(), direction.parse::<Direction>().unwrap())),
|
||||
_ => Err(()),
|
||||
},
|
||||
_ => Err(())
|
||||
},
|
||||
Some("Stop") => match parts.next() {
|
||||
Some(player_id) => Ok(Command::StopPlayer(player_id.to_string())),
|
||||
_ => Err(())
|
||||
},
|
||||
Some("UpdateBoxArea") => match parts.next() {
|
||||
Some(position) => {
|
||||
let position = position.parse::<BoxAreaPosition>().unwrap();
|
||||
match parts.next() {
|
||||
Some(content) => {
|
||||
let content = content.parse::<BoxAreaContent>().unwrap();
|
||||
Ok(Command::UpdateBoxArea(position, content))
|
||||
}
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
_ => Err(()),
|
||||
},
|
||||
Some(_) | None => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::world::Direction::{Left, Up};
|
||||
use crate::world::{BoxAreaContent, BoxAreaPosition, Command};
|
||||
|
||||
#[test]
|
||||
fn should_deserialize_command_line() {
|
||||
assert_eq!(
|
||||
Command::SpawnPlayer("1234".to_string(), 100, 200),
|
||||
"Spawn 1234 100 200".parse::<Command>().unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Command::RemovePlayer("1234".to_string()),
|
||||
"Remove 1234".parse::<Command>().unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Command::FacePlayer("1234".to_string(), Left),
|
||||
"Face 1234 Left".parse::<Command>().unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
Command::MovePlayer("1234".to_string(), Up),
|
||||
"Move 1234 Up".parse::<Command>().unwrap()
|
||||
);
|
||||
assert_eq!(Command::StopPlayer("1234".to_string()), "Stop 1234".parse::<Command>().unwrap());
|
||||
assert_eq!(
|
||||
Command::UpdateBoxArea(BoxAreaPosition::RightBottom, BoxAreaContent::HiddenBox),
|
||||
"UpdateBoxArea RightBottom HiddenBox"
|
||||
.parse::<Command>()
|
||||
.unwrap()
|
||||
);
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
use rand::random;
|
||||
use crate::sprite::Sprite;
|
||||
use crate::{sprite, GLASS_SPACE};
|
||||
use sdl2::rect::{Point, Rect};
|
||||
@ -5,6 +6,7 @@ use sdl2::render::{Texture, WindowCanvas};
|
||||
|
||||
/// The player with his position, direction ...
|
||||
pub struct Player {
|
||||
pub id: String,
|
||||
position: Point,
|
||||
direction: PlayerDirection,
|
||||
footstep: u8,
|
||||
@ -24,8 +26,13 @@ enum PlayerDirection {
|
||||
impl Player {
|
||||
/// Initializes Player with fixed position and direction.
|
||||
pub fn init() -> Player {
|
||||
Self::spawn(random::<u32>().to_string().as_str(), 380, 250)
|
||||
}
|
||||
|
||||
pub fn spawn(player_id: &str, x: u32, y: u32) -> Player {
|
||||
Player {
|
||||
position: Point::new(380, 250),
|
||||
id: player_id.to_string(),
|
||||
position: Point::new(x as i32, y as i32),
|
||||
direction: PlayerDirection::Down,
|
||||
footstep: 0,
|
||||
empty_glasses: 0,
|
||||
|
161
src/world.rs
161
src/world.rs
@ -10,6 +10,7 @@ use crate::{Player, GLASS_SPACE};
|
||||
|
||||
pub struct World {
|
||||
player: Player,
|
||||
remote_player: Option<Player>,
|
||||
right_top_box_area: BoxArea,
|
||||
right_bottom_box_area: BoxArea,
|
||||
left_bottom_box_area: BoxArea,
|
||||
@ -23,6 +24,7 @@ impl World {
|
||||
pub fn init() -> World {
|
||||
World {
|
||||
player: Player::init(),
|
||||
remote_player: None,
|
||||
right_top_box_area: BoxArea::new(BoxAreaPosition::RightTop, BoxAreaContent::EmptyGlass),
|
||||
right_bottom_box_area: BoxArea::new(
|
||||
BoxAreaPosition::RightBottom,
|
||||
@ -43,6 +45,14 @@ impl World {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn spawn_player(&mut self, player_id: String, x: u32, y: u32) {
|
||||
self.remote_player = Some(Player::spawn(player_id.as_str(), x, y));
|
||||
}
|
||||
|
||||
pub fn get_player(&mut self, _: String) -> &mut Player {
|
||||
&mut self.player
|
||||
}
|
||||
|
||||
pub fn playable_rect() -> Rect {
|
||||
Rect::new(0, 50, 800, 550)
|
||||
}
|
||||
@ -52,58 +62,120 @@ impl World {
|
||||
/// This checks if player collides with any stop item or will move out of world.
|
||||
/// If player can move, move him and turn him to the correct side.
|
||||
pub fn handle_event(&mut self, event: Event) {
|
||||
let player_id = self.player.id.clone();
|
||||
match event {
|
||||
Event::KeyDown {
|
||||
keycode: Some(Keycode::Up) | Some(Keycode::W),
|
||||
..
|
||||
} => {
|
||||
self.player.move_up();
|
||||
self.execute_command(Command::MovePlayer(player_id.clone(), Direction::Up));
|
||||
if self.collides_with_stop() || !self.player.within_rect(&Self::playable_rect()) {
|
||||
self.player.move_down();
|
||||
self.player.face_up();
|
||||
self.execute_command(Command::MovePlayer(player_id.clone(), Direction::Down));
|
||||
self.execute_command(Command::FacePlayer(player_id.clone(), Direction::Up));
|
||||
}
|
||||
}
|
||||
Event::KeyDown {
|
||||
keycode: Some(Keycode::Down) | Some(Keycode::S),
|
||||
..
|
||||
} => {
|
||||
self.player.move_down();
|
||||
self.execute_command(Command::MovePlayer(player_id.clone(), Direction::Down));
|
||||
if self.collides_with_stop() || !self.player.within_rect(&Self::playable_rect()) {
|
||||
self.player.move_up();
|
||||
self.player.face_down();
|
||||
self.execute_command(Command::MovePlayer(player_id.clone(), Direction::Up));
|
||||
self.execute_command(Command::FacePlayer(player_id.clone(), Direction::Down));
|
||||
}
|
||||
}
|
||||
Event::KeyDown {
|
||||
keycode: Some(Keycode::Left) | Some(Keycode::A),
|
||||
..
|
||||
} => {
|
||||
self.player.move_left();
|
||||
self.execute_command(Command::MovePlayer(player_id.clone(), Direction::Left));
|
||||
if self.collides_with_stop() || !self.player.within_rect(&Self::playable_rect()) {
|
||||
self.player.move_right();
|
||||
self.player.face_left();
|
||||
self.execute_command(Command::MovePlayer(player_id.clone(), Direction::Right));
|
||||
self.execute_command(Command::FacePlayer(player_id.clone(), Direction::Left));
|
||||
}
|
||||
}
|
||||
Event::KeyDown {
|
||||
keycode: Some(Keycode::Right) | Some(Keycode::D),
|
||||
..
|
||||
} => {
|
||||
self.player.move_right();
|
||||
self.execute_command(Command::MovePlayer(player_id.clone(), Direction::Right));
|
||||
if self.collides_with_stop() || !self.player.within_rect(&Self::playable_rect()) {
|
||||
self.player.move_left();
|
||||
self.player.face_right();
|
||||
self.execute_command(Command::MovePlayer(player_id.clone(), Direction::Left));
|
||||
self.execute_command(Command::FacePlayer(player_id.clone(), Direction::Right));
|
||||
}
|
||||
}
|
||||
Event::KeyUp { .. } => self.player.stop(),
|
||||
Event::KeyUp { .. } => self.execute_command(Command::StopPlayer(player_id.clone())),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
/// Executes a command for world update.
|
||||
pub fn execute_command(&mut self, command: Command) {
|
||||
println!("{}", command);
|
||||
|
||||
match command {
|
||||
Command::SpawnPlayer(player_id, x, y) => &mut {
|
||||
// TBD
|
||||
},
|
||||
Command::RemovePlayer(player_id) => &mut {
|
||||
// TBD
|
||||
},
|
||||
Command::FacePlayer(player_id, Direction::Down) => {
|
||||
&mut self.get_player(player_id).face_down()
|
||||
},
|
||||
Command::FacePlayer(player_id, Direction::Up) => {
|
||||
&mut self.get_player(player_id).face_up()
|
||||
},
|
||||
Command::FacePlayer(player_id, Direction::Left) => {
|
||||
&mut self.get_player(player_id).face_left()
|
||||
},
|
||||
Command::FacePlayer(player_id, Direction::Right) => {
|
||||
&mut self.get_player(player_id).face_right()
|
||||
},
|
||||
Command::MovePlayer(player_id, Direction::Down) => {
|
||||
&mut self.get_player(player_id).move_down()
|
||||
},
|
||||
Command::MovePlayer(player_id, Direction::Up) => {
|
||||
&mut self.get_player(player_id).move_up()
|
||||
},
|
||||
Command::MovePlayer(player_id, Direction::Left) => {
|
||||
&mut self.get_player(player_id).move_left()
|
||||
},
|
||||
Command::MovePlayer(player_id, Direction::Right) => {
|
||||
&mut self.get_player(player_id).move_right()
|
||||
},
|
||||
Command::StopPlayer(player_id) => {
|
||||
&mut self.get_player(player_id).stop()
|
||||
},
|
||||
Command::UpdateBoxArea(position, content) => &mut {
|
||||
match position {
|
||||
BoxAreaPosition::RightTop => {
|
||||
self.right_top_box_area.update_content(content);
|
||||
self.right_top_box_area.last_update = chrono::Utc::now().timestamp();
|
||||
}
|
||||
BoxAreaPosition::RightBottom => {
|
||||
self.right_bottom_box_area.update_content(content);
|
||||
self.right_top_box_area.last_update = chrono::Utc::now().timestamp();
|
||||
}
|
||||
BoxAreaPosition::LeftBottom => {
|
||||
self.left_bottom_box_area.update_content(content);
|
||||
self.right_top_box_area.last_update = chrono::Utc::now().timestamp();
|
||||
}
|
||||
BoxAreaPosition::LeftTop => {
|
||||
self.left_top_box_area.update_content(content);
|
||||
self.right_top_box_area.last_update = chrono::Utc::now().timestamp();
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Updates box areas to provide new boxes and remove items after some time
|
||||
pub fn update_box_areas(&mut self) {
|
||||
World::update_box_area(&mut self.right_top_box_area);
|
||||
World::update_box_area(&mut self.right_bottom_box_area);
|
||||
World::update_box_area(&mut self.left_bottom_box_area);
|
||||
World::update_box_area(&mut self.left_top_box_area);
|
||||
self.update_box_area(BoxAreaPosition::RightTop);
|
||||
self.update_box_area(BoxAreaPosition::RightBottom);
|
||||
self.update_box_area(BoxAreaPosition::LeftBottom);
|
||||
self.update_box_area(BoxAreaPosition::LeftTop);
|
||||
}
|
||||
|
||||
/// Handles both, collisions with lounge and any box area
|
||||
@ -159,6 +231,11 @@ impl World {
|
||||
// Player
|
||||
self.player.render(canvas, texture);
|
||||
|
||||
// Remote/other player
|
||||
if let Some(remote_player) = &self.remote_player {
|
||||
remote_player.render(canvas, texture);
|
||||
}
|
||||
|
||||
// Points
|
||||
let x = font
|
||||
.render(format!("Score: {:#04}", self.player.points).as_str())
|
||||
@ -177,17 +254,28 @@ impl World {
|
||||
canvas.present();
|
||||
}
|
||||
|
||||
fn update_box_area(box_area: &mut BoxArea) {
|
||||
fn update_box_area(&mut self, box_area_position: BoxAreaPosition) {
|
||||
let box_area = match box_area_position {
|
||||
BoxAreaPosition::RightTop => &self.right_top_box_area,
|
||||
BoxAreaPosition::RightBottom => &self.right_bottom_box_area,
|
||||
BoxAreaPosition::LeftBottom => &self.left_bottom_box_area,
|
||||
BoxAreaPosition::LeftTop => &self.left_top_box_area,
|
||||
};
|
||||
|
||||
let now = chrono::Utc::now().timestamp();
|
||||
let r: i64 = (rand::random::<i64>() % 10) + 3;
|
||||
|
||||
if box_area.content == BoxAreaContent::Nothing && box_area.last_update + 10 < now {
|
||||
box_area.content = BoxAreaContent::HiddenBox;
|
||||
box_area.last_update = now;
|
||||
self.execute_command(Command::UpdateBoxArea(
|
||||
box_area_position,
|
||||
BoxAreaContent::HiddenBox,
|
||||
));
|
||||
} else if box_area.content != BoxAreaContent::Nothing && box_area.last_update + 30 < now - r
|
||||
{
|
||||
box_area.content = BoxAreaContent::Nothing;
|
||||
box_area.last_update = now;
|
||||
self.execute_command(Command::UpdateBoxArea(
|
||||
box_area_position,
|
||||
BoxAreaContent::Nothing,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@ -239,6 +327,7 @@ impl World {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO Commands
|
||||
fn handle_boxarea_collisions(&mut self) {
|
||||
if let Collision::BoxArea(bap) = self.has_player_collision() {
|
||||
let ba = match bap {
|
||||
@ -256,20 +345,38 @@ impl World {
|
||||
};
|
||||
|
||||
if content == BoxAreaContent::EmptyGlass && self.player.can_pick_glass() {
|
||||
ba.update_content(BoxAreaContent::Nothing);
|
||||
self.execute_command(Command::UpdateBoxArea(bap, BoxAreaContent::Nothing));
|
||||
self.player.pick_glass();
|
||||
} else if content == BoxAreaContent::EmptyGlass && !self.player.can_pick_glass() {
|
||||
ba.update_content(BoxAreaContent::EmptyGlass);
|
||||
self.execute_command(Command::UpdateBoxArea(bap, BoxAreaContent::EmptyGlass));
|
||||
} else if content == BoxAreaContent::FilledBottle && self.player.can_fill_glass() {
|
||||
ba.update_content(BoxAreaContent::EmptyBottle);
|
||||
self.execute_command(Command::UpdateBoxArea(bap, BoxAreaContent::EmptyBottle));
|
||||
self.player.fill_glass();
|
||||
} else if content == BoxAreaContent::FilledBottle && !self.player.can_fill_glass() {
|
||||
ba.update_content(BoxAreaContent::FilledBottle);
|
||||
self.execute_command(Command::UpdateBoxArea(bap, BoxAreaContent::FilledBottle));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum Direction {
|
||||
Up,
|
||||
Down,
|
||||
Left,
|
||||
Right,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum Command {
|
||||
SpawnPlayer(String, u32, u32),
|
||||
RemovePlayer(String),
|
||||
FacePlayer(String, Direction),
|
||||
MovePlayer(String, Direction),
|
||||
StopPlayer(String),
|
||||
UpdateBoxArea(BoxAreaPosition, BoxAreaContent),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
enum Collision {
|
||||
BoxArea(BoxAreaPosition),
|
||||
@ -317,7 +424,7 @@ impl BoxArea {
|
||||
Rect::new(x_offset, y_offset, 110, 110)
|
||||
}
|
||||
|
||||
/// Checks if player collides with this BoxSrea
|
||||
/// Checks if player collides with this BoxArea
|
||||
fn collides_with(&self, player: &Player) -> bool {
|
||||
self.bounding_rect().contains_point(player.center())
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user