diff options
30 files changed, 1850 insertions, 92 deletions
@@ -27,6 +27,12 @@ dependencies = [ ] [[package]] +name = "aligned-vec" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4aa90d7ce82d4be67b64039a3d588d38dbcc6736577de4a847025ce5b0c468d1" + +[[package]] name = "anstream" version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -82,6 +88,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] +name = "arbitrary" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" + +[[package]] +name = "arg_enum_proc_macro" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + +[[package]] name = "async-compression" version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -102,6 +131,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] +name = "av1-grain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6678909d8c5d46a42abcf571271e15fdbc0a225e3646cf23762cd415046c78bf" +dependencies = [ + "anyhow", + "arrayvec", + "log", + "nom", + "num-rational", + "v_frame", +] + +[[package]] +name = "avif-serialize" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "876c75a42f6364451a033496a14c44bffe41f5f4a8236f697391f11024e596d2" +dependencies = [ + "arrayvec", +] + +[[package]] name = "aws-lc-rs" version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -150,12 +202,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] +name = "bincode" +version = "2.0.0-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f11ea1a0346b94ef188834a65c068a03aec181c94896d481d7a0a40d85b0ce95" +dependencies = [ + "bincode_derive", + "serde", +] + +[[package]] +name = "bincode_derive" +version = "2.0.0-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e30759b3b99a1b802a7a3aa21c85c3ded5c28e1c83170d82d70f08bbf7f3e4c" +dependencies = [ + "virtue", +] + +[[package]] name = "bindgen" version = "0.69.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" dependencies = [ - "bitflags", + "bitflags 2.6.0", "cexpr", "clang-sys", "itertools", @@ -173,12 +244,30 @@ dependencies = [ ] [[package]] +name = "bit_field" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] name = "bitflags" version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] +name = "bitstream-io" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dcde5f311c85b8ca30c2e4198d4326bc342c76541590106f5fa4a50946ea499" + +[[package]] name = "block-buffer" version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -188,26 +277,49 @@ dependencies = [ ] [[package]] +name = "built" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "236e6289eda5a812bc6b53c3b024039382a2895fbbeef2d748b2931546d392c4" + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "bytemuck" +version = "1.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e" + +[[package]] name = "byteorder" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] +name = "byteorder-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" + +[[package]] name = "bytes" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +checksum = "a12916984aab3fa6e39d655a33e09c0071eb36d6ab3aea5c2d78551f1df6d952" [[package]] name = "cc" -version = "1.0.106" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "066fce287b1d4eafef758e89e09d724a24808a9196fe9756b8ca90e86d0719a2" +checksum = "324c74f2155653c90b04f25b2a47a8a631360cb908f92a772695f430c7e31052" dependencies = [ "jobserver", "libc", - "once_cell", ] [[package]] @@ -220,6 +332,16 @@ dependencies = [ ] [[package]] +name = "cfg-expr" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" +dependencies = [ + "smallvec", + "target-lexicon", +] + +[[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -238,9 +360,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.8" +version = "4.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84b3edb18336f4df585bc9aa31dd99c036dfa5dc5e9a2939a722a188f3a8970d" +checksum = "64acc1846d54c1fe936a78dc189c34e28d3f5afc348403f28ecf53660b9b8462" dependencies = [ "clap_builder", "clap_derive", @@ -248,9 +370,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.8" +version = "4.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1c09dd5ada6c6c78075d6fd0da3f90d8080651e2d6cc8eb2f1aaa4034ced708" +checksum = "6fb8393d67ba2e7bfaf28a23458e4e2b543cc73a99595511eb207fdb8aede942" dependencies = [ "anstream", "anstyle", @@ -286,6 +408,12 @@ dependencies = [ ] [[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + +[[package]] name = "colorchoice" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -317,6 +445,46 @@ dependencies = [ ] [[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] name = "crypto-common" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -400,6 +568,22 @@ dependencies = [ ] [[package]] +name = "exr" +version = "1.72.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "887d93f60543e9a9362ef8a21beedd0a833c5d9610e18c67abe15a5963dcb1a4" +dependencies = [ + "bit_field", + "flume", + "half", + "lebe", + "miniz_oxide", + "rayon-core", + "smallvec", + "zune-inflate", +] + +[[package]] name = "fake" version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -410,6 +594,40 @@ dependencies = [ ] [[package]] +name = "fastrand" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" + +[[package]] +name = "fdeflate" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "flate2" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "flume" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" +dependencies = [ + "spin", +] + +[[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -487,6 +705,16 @@ dependencies = [ ] [[package]] +name = "gif" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb2d69b19215e18bb912fa30f7ce15846e301408695e44e0ef719f1da9e19f2" +dependencies = [ + "color_quant", + "weezl", +] + +[[package]] name = "gimli" version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -508,6 +736,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] +name = "half" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +dependencies = [ + "cfg-if", + "crunchy", +] + +[[package]] name = "hashbrown" version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -561,6 +799,7 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" name = "hurrycurry-protocol" version = "0.1.0" dependencies = [ + "bincode", "glam", "serde", ] @@ -589,6 +828,7 @@ name = "hurrycurry-server" version = "0.2.0" dependencies = [ "anyhow", + "bincode", "clap", "env_logger", "fake", @@ -599,13 +839,52 @@ dependencies = [ "rand 0.9.0-alpha.1", "serde", "serde_json", - "serde_yaml", + "serde_yml", "shlex", "tokio", "tokio-tungstenite", ] [[package]] +name = "image" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd54d660e773627692c524beaad361aca785a4f9f5730ce91f42aabe5bce3d11" +dependencies = [ + "bytemuck", + "byteorder", + "color_quant", + "exr", + "gif", + "image-webp", + "num-traits", + "png", + "qoi", + "ravif", + "rayon", + "rgb", + "tiff", + "zune-core", + "zune-jpeg", +] + +[[package]] +name = "image-webp" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d730b085583c4d789dfd07fdcf185be59501666a90c97c40162b37e4fdad272d" +dependencies = [ + "byteorder-lite", + "thiserror", +] + +[[package]] +name = "imgref" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44feda355f4159a7c757171a77de25daf6411e217b4cabd03bd6650690468126" + +[[package]] name = "indexmap" version = "2.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -616,6 +895,17 @@ dependencies = [ ] [[package]] +name = "interpolate_name" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] name = "is_terminal_polyfill" version = "1.70.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -646,6 +936,12 @@ dependencies = [ ] [[package]] +name = "jpeg-decoder" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" + +[[package]] name = "lazy_static" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -658,12 +954,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] +name = "lebe" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" + +[[package]] name = "libc" version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] +name = "libfuzzer-sys" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a96cfd5557eb82f2b83fed4955246c988d331975a002961b07c81584d107e7f7" +dependencies = [ + "arbitrary", + "cc", + "once_cell", +] + +[[package]] name = "libloading" version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -674,6 +987,25 @@ dependencies = [ ] [[package]] +name = "libyml" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e281a65eeba3d4503a2839252f86374528f9ceafe6fed97c1d3b52e1fb625c1" + +[[package]] +name = "light-client" +version = "0.1.0" +dependencies = [ + "bincode", + "env_logger", + "hurrycurry-protocol", + "log", + "sdl2", + "serde_json", + "tungstenite", +] + +[[package]] name = "linux-raw-sys" version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -696,6 +1028,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] +name = "loop9" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" +dependencies = [ + "imgref", +] + +[[package]] +name = "maybe-rayon" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" +dependencies = [ + "cfg-if", + "rayon", +] + +[[package]] name = "memchr" version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -714,6 +1065,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" dependencies = [ "adler", + "simd-adler32", ] [[package]] @@ -734,6 +1086,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9be0862c1b3f26a88803c4a49de6889c10e608b3ee9344e6ef5b45fb37ad3d1" [[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] name = "nom" version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -744,6 +1102,62 @@ dependencies = [ ] [[package]] +name = "noop_proc_macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] name = "num_cpus" version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -822,6 +1236,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] +name = "png" +version = "0.17.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06e4b0d3d1312775e782c86c91a111aa1f910cbb65e1337f9975b5f9a554b5e1" +dependencies = [ + "bitflags 1.3.2", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + +[[package]] name = "pollster" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -853,6 +1280,40 @@ dependencies = [ ] [[package]] +name = "profiling" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d84d1d7a6ac92673717f9f6d1518374ef257669c24ebc5ac25d5033828be58" +dependencies = [ + "profiling-procmacros", +] + +[[package]] +name = "profiling-procmacros" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8021cf59c8ec9c432cfc2526ac6b8aa508ecaf29cd415f271b8406c1b851c3fd" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "qoi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + +[[package]] name = "quote" version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -923,12 +1384,82 @@ dependencies = [ ] [[package]] +name = "rav1e" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd87ce80a7665b1cce111f8a16c1f3929f6547ce91ade6addf4ec86a8dda5ce9" +dependencies = [ + "arbitrary", + "arg_enum_proc_macro", + "arrayvec", + "av1-grain", + "bitstream-io", + "built", + "cfg-if", + "interpolate_name", + "itertools", + "libc", + "libfuzzer-sys", + "log", + "maybe-rayon", + "new_debug_unreachable", + "noop_proc_macro", + "num-derive", + "num-traits", + "once_cell", + "paste", + "profiling", + "rand 0.8.5", + "rand_chacha 0.3.1", + "simd_helpers", + "system-deps", + "thiserror", + "v_frame", + "wasm-bindgen", +] + +[[package]] +name = "ravif" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6ba61c28ba24c0cf8406e025cb29a742637e3f70776e61c27a8a8b72a042d12" +dependencies = [ + "avif-serialize", + "imgref", + "loop9", + "quick-error", + "rav1e", + "rayon", + "rgb", +] + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] name = "redox_syscall" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" +checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" dependencies = [ - "bitflags", + "bitflags 2.6.0", ] [[package]] @@ -961,6 +1492,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] +name = "rgb" +version = "0.8.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aee83dc281d5a3200d37b299acd13b81066ea126a7f16f0eae70fc9aed241d9" +dependencies = [ + "bytemuck", +] + +[[package]] name = "ring" version = "0.17.8" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -993,7 +1533,7 @@ version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ - "bitflags", + "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", @@ -1079,12 +1619,35 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] +name = "sdl2" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b498da7d14d1ad6c839729bd4ad6fc11d90a57583605f3b4df2cd709a9cd380" +dependencies = [ + "bitflags 1.3.2", + "lazy_static", + "libc", + "sdl2-sys", +] + +[[package]] +name = "sdl2-sys" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "951deab27af08ed9c6068b7b0d05a93c91f0a8eb16b6b816a5e73452a43521d3" +dependencies = [ + "cfg-if", + "libc", + "version-compare 0.1.1", +] + +[[package]] name = "security-framework" -version = "2.11.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags", + "bitflags 2.6.0", "core-foundation", "core-foundation-sys", "libc", @@ -1093,9 +1656,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.11.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" +checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" dependencies = [ "core-foundation-sys", "libc", @@ -1133,16 +1696,29 @@ dependencies = [ ] [[package]] -name = "serde_yaml" -version = "0.9.34+deprecated" +name = "serde_spanned" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" +checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_yml" +version = "0.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ce6afeda22f0b55dde2c34897bce76a629587348480384231205c14b59a01f" dependencies = [ "indexmap", "itoa", + "libyml", + "log", + "memchr", "ryu", "serde", - "unsafe-libyaml", + "serde_json", + "tempfile", ] [[package]] @@ -1172,6 +1748,21 @@ dependencies = [ ] [[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + +[[package]] +name = "simd_helpers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" +dependencies = [ + "quote", +] + +[[package]] name = "slab" version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1201,6 +1792,9 @@ name = "spin" version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] [[package]] name = "strsim" @@ -1216,9 +1810,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.69" +version = "2.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "201fcda3845c23e8212cd466bfebf0bd20694490fc0356ae8e428e0824a915a6" +checksum = "b146dcf730474b4bcd16c311627b31ede9ab149045db4d6088b3becaea046462" dependencies = [ "proc-macro2", "quote", @@ -1226,19 +1820,50 @@ dependencies = [ ] [[package]] +name = "system-deps" +version = "6.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" +dependencies = [ + "cfg-expr", + "heck", + "pkg-config", + "toml", + "version-compare 0.2.0", +] + +[[package]] +name = "target-lexicon" +version = "0.12.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4873307b7c257eddcb50c9bedf158eb669578359fb28428bef438fec8e6ba7c2" + +[[package]] +name = "tempfile" +version = "3.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +dependencies = [ + "cfg-if", + "fastrand", + "rustix", + "windows-sys 0.52.0", +] + +[[package]] name = "thiserror" -version = "1.0.61" +version = "1.0.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" +checksum = "f2675633b1499176c2dff06b0856a27976a8f9d436737b4cf4f312d4d91d8bbb" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.61" +version = "1.0.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" +checksum = "d20468752b09f49e909e55a5d338caa8bedf615594e9d80bc4c565d30faf798c" dependencies = [ "proc-macro2", "quote", @@ -1246,6 +1871,17 @@ dependencies = [ ] [[package]] +name = "tiff" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e" +dependencies = [ + "flate2", + "jpeg-decoder", + "weezl", +] + +[[package]] name = "tokio" version = "1.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1303,6 +1939,51 @@ dependencies = [ ] [[package]] +name = "toml" +version = "0.8.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f49eb2ab21d2f26bd6db7bf383edc527a7ebaee412d17af4d40fdccd442f335" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59a3a72298453f564e2b111fa896f8d07fabb36f51f06d7e875fc5e0b5a3ef1" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tools" +version = "0.1.0" +dependencies = [ + "anyhow", + "clap", + "env_logger", + "image", + "log", +] + +[[package]] name = "tungstenite" version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1335,12 +2016,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] -name = "unsafe-libyaml" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" - -[[package]] name = "untrusted" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1359,18 +2034,107 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] +name = "v_frame" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f32aaa24bacd11e488aa9ba66369c7cd514885742c9fe08cfe85884db3e92b" +dependencies = [ + "aligned-vec", + "num-traits", + "wasm-bindgen", +] + +[[package]] +name = "version-compare" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29" + +[[package]] +name = "version-compare" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" + +[[package]] name = "version_check" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] +name = "virtue" +version = "0.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dcc60c0624df774c82a0ef104151231d37da4962957d691c011c852b2473314" + +[[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] +name = "wasm-bindgen" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" + +[[package]] +name = "weezl" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" + +[[package]] name = "which" version = "4.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1522,6 +2286,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] +name = "winnow" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59b5e5f6c299a3c7890b876a2a587f3115162487e704907d9b6cd29473052ba1" +dependencies = [ + "memchr", +] + +[[package]] name = "zerocopy" version = "0.8.0-alpha.6" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1588,3 +2361,27 @@ dependencies = [ "cc", "pkg-config", ] + +[[package]] +name = "zune-core" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" + +[[package]] +name = "zune-inflate" +version = "0.2.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "zune-jpeg" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec866b44a2a1fd6133d363f073ca1b179f438f99e7e5bfb1e33f7181facfe448" +dependencies = [ + "zune-core", +] @@ -1,3 +1,9 @@ [workspace] -members = ["server/replaytool", "server", "server/protocol"] +members = [ + "server/replaytool", + "server", + "server/protocol", + "light-client", + "light-client/tools", +] resolver = "2" diff --git a/light-client/Cargo.toml b/light-client/Cargo.toml new file mode 100644 index 00000000..ad50130c --- /dev/null +++ b/light-client/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "light-client" +version = "0.1.0" +edition = "2021" + +[dependencies] +sdl2 = { version = "0.37.0", features = ["image", "ttf"] } +hurrycurry-protocol = { path = "../server/protocol" } +tungstenite = "0.23.0" +serde_json = "1.0.120" +bincode = "2.0.0-rc.3" +log = "0.4.22" +env_logger = "0.11.3" diff --git a/light-client/src/bin/bunnymark.rs b/light-client/src/bin/bunnymark.rs new file mode 100644 index 00000000..12c18d66 --- /dev/null +++ b/light-client/src/bin/bunnymark.rs @@ -0,0 +1,104 @@ +/* + Hurry Curry! - a game about cooking + Copyright 2024 metamuffin + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, version 3 of the License only. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. + +*/ +use hurrycurry_protocol::glam::IVec2; +use sdl2::{ + event::Event, + image::{InitFlag, LoadTexture}, + keyboard::Keycode, + pixels::Color, + rect::Rect, +}; +use std::time::Instant; + +const WIDTH: i32 = 1920; +const HEIGHT: i32 = 1080; + +pub fn main() { + let amount = std::env::args().skip(1).next().unwrap().parse().unwrap(); + + let sdl_context = sdl2::init().unwrap(); + let video_subsystem = sdl_context.video().unwrap(); + let _image_context = sdl2::image::init(InitFlag::WEBP | InitFlag::PNG).unwrap(); + let window = video_subsystem + .window("Hurry Curry! Light Client", WIDTH as u32, HEIGHT as u32) + .position_centered() + .build() + .map_err(|e| e.to_string()) + .unwrap(); + + let mut canvas = window + .into_canvas() + .accelerated() + .build() + .map_err(|e| e.to_string()) + .unwrap(); + let texture_creator = canvas.texture_creator(); + let texture = texture_creator.load_texture("client/icon.png").unwrap(); + + let mut bunnies = vec![(IVec2::ZERO, IVec2::ONE); amount]; + + for (i, (pos, vel)) in bunnies.iter_mut().enumerate() { + let mut r = xorshift(i as i32); + pos.x = r % WIDTH; + r = xorshift(r); + pos.y = r % HEIGHT; + r = xorshift(r); + vel.x = r % 7 - 3; + r = xorshift(r); + vel.y = r % 7 - 3; + } + + let mut last = Instant::now(); + 'mainloop: loop { + canvas.set_draw_color(Color::BLACK); + canvas.clear(); + for (pos, vel) in &mut bunnies { + *pos += *vel; + if pos.x < 0 || pos.x > WIDTH { + vel.x *= -1 + } + if pos.y < 0 || pos.y > HEIGHT { + vel.y *= -1 + } + canvas + .copy(&texture, None, Some(Rect::new(pos.x, pos.y, 30, 30))) + .unwrap(); + } + canvas.present(); + + for event in sdl_context.event_pump().unwrap().poll_iter() { + match event { + Event::Quit { .. } + | Event::KeyDown { + keycode: Option::Some(Keycode::Escape), + .. + } => break 'mainloop, + _ => {} + } + } + println!("frame time: {:?}", last.elapsed()); + last = Instant::now(); + } +} + +fn xorshift(mut x: i32) -> i32 { + x ^= x << 13; + x ^= x >> 17; + x ^= x << 5; + x +} diff --git a/light-client/src/game.rs b/light-client/src/game.rs new file mode 100644 index 00000000..fd045f53 --- /dev/null +++ b/light-client/src/game.rs @@ -0,0 +1,4 @@ + +pub struct Game { + +} diff --git a/light-client/src/main.rs b/light-client/src/main.rs new file mode 100644 index 00000000..85254ef4 --- /dev/null +++ b/light-client/src/main.rs @@ -0,0 +1,81 @@ +use network::Network; +/* + Hurry Curry! - a game about cooking + Copyright 2024 metamuffin + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, version 3 of the License only. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. + +*/ +use sdl2::{ + event::Event, + image::InitFlag, + keyboard::Keycode, + pixels::{Color, PixelFormatEnum}, + render::TextureAccess, +}; + +pub mod network; +pub mod game; + +fn main() { + let net = Network::connect("ws://127.0.0.1:27032/"); + + let sdl_context = sdl2::init().unwrap(); + let video_subsystem = sdl_context.video().unwrap(); + let _image_context = sdl2::image::init(InitFlag::WEBP).unwrap(); + let window = video_subsystem + .window("Hurry Curry! Light Client", 1280, 720) + .position_centered() + .resizable() + .build() + .map_err(|e| e.to_string()) + .unwrap(); + + let mut canvas = window + .into_canvas() + .accelerated() + .build() + .map_err(|e| e.to_string()) + .unwrap(); + let texture_creator = canvas.texture_creator(); + let mut texture = texture_creator + .create_texture( + Some(PixelFormatEnum::RGBA8888), + TextureAccess::Streaming, + 1024, + 1024, + ) + .unwrap(); + + texture.update(None, &vec![128; 1024 * 1024], 1024).unwrap(); + + 'mainloop: loop { + canvas.set_draw_color(Color::BLACK); + canvas.clear(); + + canvas.copy(&texture, None, None).unwrap(); + + canvas.present(); + + for event in sdl_context.event_pump().unwrap().poll_iter() { + match event { + Event::Quit { .. } + | Event::KeyDown { + keycode: Option::Some(Keycode::Escape), + .. + } => break 'mainloop, + _ => {} + } + } + } +} diff --git a/light-client/src/network.rs b/light-client/src/network.rs new file mode 100644 index 00000000..dc6e894f --- /dev/null +++ b/light-client/src/network.rs @@ -0,0 +1,52 @@ +use hurrycurry_protocol::{PacketC, PacketS, BINCODE_CONFIG}; +use log::warn; +use std::{collections::VecDeque, net::TcpStream}; +use tungstenite::{stream::MaybeTlsStream, Message, WebSocket}; + +pub struct Network { + sock: WebSocket<MaybeTlsStream<TcpStream>>, + queue_in: VecDeque<PacketC>, + queue_out: VecDeque<PacketS>, +} + +impl Network { + pub fn connect(addr: &str) -> Self { + let (sock, _resp) = tungstenite::connect(addr).unwrap(); + Self { + sock, + queue_in: VecDeque::new(), + queue_out: VecDeque::new(), + } + } + pub fn poll(&mut self) { + self.queue_in.extend(match self.sock.read() { + Ok(Message::Text(packet)) => match serde_json::from_str(&packet) { + Ok(p) => Some(p), + Err(e) => { + warn!("invalid json packet: {e:?}"); + None + } + }, + Ok(Message::Binary(packet)) => { + match bincode::decode_from_slice(&packet, BINCODE_CONFIG) { + Ok((p, _)) => Some(p), + Err(e) => { + warn!("invalid bincode packet: {e:?}"); + None + } + } + } + Ok(_) => None, + Err(e) => { + warn!("{e:?}"); + None + } + }); + + for packet in self.queue_out.drain(..) { + self.sock + .write(Message::Text(serde_json::to_string(&packet).unwrap())) + .unwrap(); + } + } +} diff --git a/light-client/textures/.gitignore b/light-client/textures/.gitignore new file mode 100644 index 00000000..e33609d2 --- /dev/null +++ b/light-client/textures/.gitignore @@ -0,0 +1 @@ +*.png diff --git a/light-client/textures/makefile b/light-client/textures/makefile new file mode 100644 index 00000000..1dd60ff4 --- /dev/null +++ b/light-client/textures/makefile @@ -0,0 +1,16 @@ + + +ALL_TA = $(patsubst %.png,%.ta,$(shell find -name '*.png')) +ALL_PNG = $(patsubst %.ta,%.png,$(shell find -name '*.ta')) + +.PHONY: tex_export tex_import clean +tex_import: $(ALL_TA) +tex_export: $(ALL_PNG) +clean: + rm $(ALL_PNG) + +%.ta: %.png + ../../target/release/tex_import $< $@ +%.png: %.ta + ../../target/release/tex_export $< $@ + diff --git a/light-client/textures/palette.csv b/light-client/textures/palette.csv new file mode 100644 index 00000000..985d23ab --- /dev/null +++ b/light-client/textures/palette.csv @@ -0,0 +1,121 @@ + ,0,0,0,0 +a,255,255,255,255 +b,242,242,242,255 +c,230,230,230,255 +d,217,217,217,255 +e,204,204,204,255 +f,191,191,191,255 +g,178,178,178,255 +h,166,166,166,255 +i,153,153,153,255 +j,140,140,140,255 +k,128,128,128,255 +l,115,115,115,255 +m,102,102,102,255 +n,89,89,89,255 +o,76,76,76,255 +p,64,64,64,255 +q,51,51,51,255 +r,38,38,38,255 +s,26,26,26,255 +t,0,0,0,255 +u,242,252,36,255 +v,255,234,0,255 +w,254,167,17,255 +x,254,139,104,255 +y,251,59,2,255 +z,254,53,33,255 +A,208,0,0,255 +B,168,31,61,255 +C,120,4,34,255 +D,43,0,0,255 +E,241,226,197,255 +F,254,228,179,255 +G,254,218,187,255 +H,254,194,142,255 +I,216,143,87,255 +J,189,99,64,255 +K,162,64,43,255 +L,99,53,45,255 +M,107,40,51,255 +N,52,18,12,255 +O,231,203,143,255 +P,209,179,139,255 +Q,193,177,127,255 +R,215,152,11,255 +S,255,177,0,255 +T,254,139,0,255 +U,255,106,0,255 +V,183,65,0,255 +W,95,62,29,255 +X,59,35,0,255 +Y,254,202,218,255 +Z,254,101,203,255 +0,254,19,146,255 +1,221,48,98,255 +2,192,74,109,255 +3,137,22,136,255 +4,77,38,137,255 +5,68,21,33,255 +6,44,17,57,255 +7,36,20,34,255 +8,255,255,125,255 +9,255,255,0,255 +!,255,127,0,255 +",255,125,125,255 +§,255,125,255,255 +$,255,0,254,255 +%,255,0,127,255 +&,255,0,0,255 +/,127,0,0,255 +(,10,10,0,255 +),246,253,255,255 +=,233,247,255,255 +?,207,230,254,255 +[,170,199,254,255 +],119,179,254,255 +{,30,116,253,255 +},0,70,170,255 +^,47,68,118,255 ++,0,48,82,255 +-,14,14,37,255 +*,238,245,240,255 +~,214,229,222,255 +#,172,216,185,255 +',108,173,198,255 +.,66,169,175,255 +:,0,127,127,255 +;,73,103,92,255 +\,46,78,78,255 +<,29,50,57,255 +>,15,28,33,255 +|,216,255,244,255 +ö,184,244,245,255 +ä,174,204,181,255 +ü,118,197,120,255 +Ö,53,135,87,255 +Ä,64,155,104,255 +Ü,70,135,104,255 +ß,31,81,43,255 +¿,42,60,55,255 +¡,18,46,29,255 +ẞ,239,255,201,255 +Æ,230,243,133,255 +æ,188,245,28,255 +€,212,220,24,255 +Ø,130,211,34,255 +ł,92,127,0,255 +Ł,89,147,43,255 +Ω,41,127,0,255 +€,0,67,32,255 +«,28,51,34,255 +»,0,255,127,255 +‹,0,255,0,255 +›,125,255,125,255 +„,125,255,255,255 +“,0,255,255,255 +@,125,125,255,255 +Ŧ,127,0,255,255 +ŧ,0,0,255,255 +ø,63,0,127,255 +¤,0,0,127,255 diff --git a/light-client/textures/tiles/counter.ta b/light-client/textures/tiles/counter.ta new file mode 100644 index 00000000..846fdbe3 --- /dev/null +++ b/light-client/textures/tiles/counter.ta @@ -0,0 +1,36 @@ +KKKJJJJJJJJJJJJJJJJJJJJJJJJJJKKK +KJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJK +KJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJK +JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJK +JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJK +JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJK +JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJK +JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ +JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ +JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ +JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ +JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ +JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ +JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ +JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ +JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ +JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ +JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ +JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ +JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJK +JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ +KJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ +KJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJK +JJKKKKKJJJJJJJJJJJJJJJJJJJKKKKKK +LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL +LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL +IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII +IPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPI +IPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP +IPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP +IPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP +PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP +IPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPI +IPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPI +IPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPI +IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII diff --git a/light-client/textures/tiles/crate_back.ta b/light-client/textures/tiles/crate_back.ta new file mode 100644 index 00000000..2f434d67 --- /dev/null +++ b/light-client/textures/tiles/crate_back.ta @@ -0,0 +1,36 @@ +NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN +NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN +NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN +NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN +NLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL +NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN +NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN +NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN +NLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL +NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN +NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN +NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN +NLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL +NNNNNNNLNNNNNNNNLNNNNNNNLNNNNNNN +NNNNNNNLNNNNNNNNLNNNNNNNLNNNNNNN +NNNNNNNLNNNNNNNNLNNNNNNNLNNNNNNN +NNNNNNNLNNNNNNNNLNNNNNNNLNNNNNNN +NNNNNNNLNNNNNNNNLNNNNNNNLNNNNNNN +NNNNNNNLNNNNNNNLLNNNNNNNLNNNNNNN +NNNNNNNLNNNNNNNLNNNNNNNNLNNNNNNN +NNNNNNNLNNNNNNNLNNNNNNNNLNNNNNNN +NNNNNNNLNNNNNNNLNNNNNNNNLNNNNNNN +NNNNNNNLNNNNNNNLNNNNNNNNLNNNNNNN +NNNNNNNNNNNNNNNLNNNNNNNNNNNNNNNN +NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN +NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN +NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN +NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN +NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN +NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN +NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN +NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN +NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN +NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN +NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN +NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN diff --git a/light-client/textures/tiles/crate_front.ta b/light-client/textures/tiles/crate_front.ta new file mode 100644 index 00000000..ff6e2d83 --- /dev/null +++ b/light-client/textures/tiles/crate_front.ta @@ -0,0 +1,36 @@ +LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL +L L +L L +L L +L L +L L +L L +L L +L L +L L +L L +L L +L L +L L +L L +L L +L L +L L +L L +L L +L L +L L +L L +LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL +KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK +LKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKL +KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK +L L +LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL +KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK +LKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKL +KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK +L L +LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL +KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK +LKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKL diff --git a/light-client/textures/tiles/cutting_board.ta b/light-client/textures/tiles/cutting_board.ta new file mode 100644 index 00000000..e6137c94 --- /dev/null +++ b/light-client/textures/tiles/cutting_board.ta @@ -0,0 +1,36 @@ + + + xPPxxxxxxxxxxxxxxxxxxPPP + xxxxxxxxxxxxxxxxxxxxxxxP + PxxxxxxxxxxxxxxxxxxxxxxP + Pxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxxxxxx + Pxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxxxxxP + Pxxxxxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxxxxxP + xxxxxxxxxxxxxxxxxxxxxxxP + PxxxxxxxxxxxxxxxxxxxxxxP + PPPxxxxxxxxxxxxxxxxxxPPP + LLLLLLLLLLLLLLLLLLLLLLLL + + + + + + + + + + + + + + + diff --git a/light-client/textures/tiles/plate.ta b/light-client/textures/tiles/plate.ta new file mode 100644 index 00000000..6766989f --- /dev/null +++ b/light-client/textures/tiles/plate.ta @@ -0,0 +1,36 @@ + + ffffffffffff + fffjjjjjjjjfff + fffjjjjjjjjjjjjfff + fffjjjjjjjjjjjjjjjff + fffjjjffffffffffffjjff + fffjjfffffffffffffffjjff + ffjjfffffffffffffffffjjff + ffjfffffffffffffffffffjff + ffffffffffffffffffffffffff + fffffffffffffffffffffffffff + fffffffffffffffffffffffffff + fffffffffffffffffffffffffff + fffffffffffffffffffffffffff + fffffffffffffffffffffffffff + ffffffffffffffffffffffffff + fffffffffffffffffffffffjf + fjfffffffffffffffffffffj + jjfffffffffffffffffffj + jjfffffffffffffffffj + jjffffffffffffffjj + jjjffffffffffjjj + jjjjjjjjjjjj + jjjjjj + + + + + + + + + + + + diff --git a/light-client/textures/tiles/player.ta b/light-client/textures/tiles/player.ta new file mode 100644 index 00000000..065a3255 --- /dev/null +++ b/light-client/textures/tiles/player.ta @@ -0,0 +1,38 @@ + eeeeeecccee + ececcccceaee + ecaeeeeccaae + eaaaaaaacaae + eacaaacaaace + eacacacaaace + eaceeeeeeeee + eeeevvvvvvv + vvvvvvvvvvvv + vvvvvvvvvvvv + vvvvvvvvvvvv + vvvvvvvvvvv + Rvvvvvvvvvv + RvvvvvvvvvR + RvvvvvvvR + RRvvvRR + wwwwRRwww + wwwwwwwvvvv + wwwwvvvvvvvv + vvwvvvvvvvvvv + vvvvvvvvvvvvvv + vvvvvvvvvvvvvvvv + vvvvvvvvvvvvvvvvvv + vvvvvvvvvvvvvvvvvvv + vvvvvvvvvvvvvvvvvvvvv + vvvvvvvvvvvvvvvvvvvvvv + vvvvvvvvvvvvvvvvvvvvvvvv + vvvvvvvvvvvvvvvvvvvvvvvv + vvvvvvvvvvvvvvvvvvvvvvvvvv + wvvvvvvvvvvvvvvvvvvvvvvvvw + wwvvvvvvvvvvvvvvvvvvvvvvww + wwwvvvvvvvvvvvvvvvvvvvwww + wwwwwvvvvvvvvvvvvvvvwwww + wwwwwwwvvvvvvvvvvwwwww + wwwwwwwwwwwwwwwwwwww + wwwwwwwwwwwwwwww + wwwwwwwwwwwwww + wwwwwwwwwwww diff --git a/light-client/textures/tiles/tomato.ta b/light-client/textures/tiles/tomato.ta new file mode 100644 index 00000000..694cbb80 --- /dev/null +++ b/light-client/textures/tiles/tomato.ta @@ -0,0 +1,36 @@ + + + + ßßÖÄ + ßßßßß + €ß €Ö + z€ßÄ€z + zÖz€¡ß€yzA + zzÄ€€€€€yAAA + zzAyy€AA€AAAAA + zAAxx€yyy€Azzz + zAAxxy€xAAzzzzy + AAAAxyxyAAzzAAy + zzAAAAAAAAzzAAy + yzzAAAAAAAzzAy + yyzzAAAAAAyAAy + yyzzAAAAyyAy + yyzzAyyyyy + yyyyyyyy + yyy + + + + + + + + + + + + + + + + diff --git a/light-client/textures/tiles/tomato_slice.ta b/light-client/textures/tiles/tomato_slice.ta new file mode 100644 index 00000000..199a3d99 --- /dev/null +++ b/light-client/textures/tiles/tomato_slice.ta @@ -0,0 +1,36 @@ + + + + + + AAAJ + AAzzAAJHAAAA + AA///zA/HAAAAAAJ + A//x//AHHA////AA + A/////zÆHA/x//AA + A/////zzÆA/////A + AA///zAzzA//x//A + Ax/zAAzz/////AA + A//zA/zz////zA + A//A//zz/x/zz + A/A//z///zzz + AAA///AAAzz + AAA//zzzz + Azzz + + + + + + + + + + + + + + + + + diff --git a/light-client/tools/Cargo.toml b/light-client/tools/Cargo.toml new file mode 100644 index 00000000..2a1dacb9 --- /dev/null +++ b/light-client/tools/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "tools" +version = "0.1.0" +edition = "2021" + +[dependencies] +image = "0.25.1" +anyhow = "1.0.86" +log = "0.4.22" +env_logger = "0.11.3" +clap = { version = "4.5.9", features = ["derive"] } diff --git a/light-client/tools/src/bin/tex_export.rs b/light-client/tools/src/bin/tex_export.rs new file mode 100644 index 00000000..2132b5ed --- /dev/null +++ b/light-client/tools/src/bin/tex_export.rs @@ -0,0 +1,58 @@ +use clap::Parser; +use image::Rgba; +use std::{ + collections::HashMap, + fs::File, + io::{BufRead, BufReader}, + path::PathBuf, +}; + +#[derive(Parser)] +struct Args { + input: PathBuf, + output: PathBuf, +} + +fn main() { + let Args { + input, + output: out_path, + } = Args::parse(); + + let palette = include_str!("../../../textures/palette.csv") + .split('\n') + .filter(|l| !l.is_empty()) + .map(|s| { + let (c, s) = s.split_once(",").unwrap(); + let (r, s) = s.split_once(",").unwrap(); + let (g, s) = s.split_once(",").unwrap(); + let (b, a) = s.split_once(",").unwrap(); + ( + c.chars().next().unwrap(), + [ + r.parse().unwrap(), + g.parse().unwrap(), + b.parse().unwrap(), + a.parse().unwrap(), + ], + ) + }) + .collect::<HashMap<_, _>>(); + + let file = BufReader::new(File::open(&input).unwrap()); + let tex = file.lines().map(Result::unwrap).collect::<Vec<String>>(); + let (width, height) = (tex[0].len(), tex.len()); + + let mut output = image::ImageBuffer::<Rgba<u8>, Vec<_>>::new(width as u32, height as u32); + + for (y, line) in tex.iter().enumerate() { + if line.is_empty() { + continue; + } + for (x, char) in line.chars().enumerate() { + output.put_pixel(x as u32, y as u32, Rgba(*palette.get(&char).unwrap())); + } + } + + output.save(out_path).unwrap(); +} diff --git a/light-client/tools/src/bin/tex_import.rs b/light-client/tools/src/bin/tex_import.rs new file mode 100644 index 00000000..89cbc8c9 --- /dev/null +++ b/light-client/tools/src/bin/tex_import.rs @@ -0,0 +1,58 @@ +use clap::Parser; +use std::{ + collections::HashMap, + fs::File, + io::{BufWriter, Write}, + path::PathBuf, + process::exit, +}; + +#[derive(Parser)] +struct Args { + input: PathBuf, + output: PathBuf, +} + +fn main() { + let Args { input, output } = Args::parse(); + + let palette = include_str!("../../../textures/palette.csv") + .split('\n') + .filter(|l| !l.is_empty()) + .map(|s| { + let (c, s) = s.split_once(",").unwrap(); + let (r, s) = s.split_once(",").unwrap(); + let (g, s) = s.split_once(",").unwrap(); + let (b, a) = s.split_once(",").unwrap(); + ( + [ + r.parse().unwrap(), + g.parse().unwrap(), + b.parse().unwrap(), + a.parse().unwrap(), + ], + c.chars().next().unwrap(), + ) + }) + .collect::<HashMap<_, _>>(); + + let input = image::open(input).unwrap().to_rgba8(); + let mut output = BufWriter::new(File::create(output).unwrap()); + + for y in 0..input.height() { + for x in 0..input.width() { + let mut c = input.get_pixel(x, y).0; + if c[3] == 0 { + c = [0, 0, 0, 0]; + } + let Some(char) = palette.get(&c) else { + eprintln!("color at {x},{y} not in palette: {c:?}"); + exit(1); + }; + write!(output, "{char}").unwrap(); + } + writeln!(output).unwrap(); + } + output.flush().unwrap(); + output.into_inner().unwrap().flush().unwrap() +} diff --git a/light-client/tools/src/bin/tex_pack.rs b/light-client/tools/src/bin/tex_pack.rs new file mode 100644 index 00000000..23056608 --- /dev/null +++ b/light-client/tools/src/bin/tex_pack.rs @@ -0,0 +1,77 @@ +use clap::Parser; +use std::{ + fs::File, + io::{BufRead, BufReader, BufWriter, Write}, + path::PathBuf, +}; + +#[derive(Parser)] +struct Args { + atlas_out: PathBuf, + atlas_meta_out: PathBuf, + inputs: Vec<PathBuf>, +} + +fn main() { + let Args { + inputs, + atlas_meta_out, + atlas_out, + } = Args::parse(); + + let atlas_size = 1024; + + let mut cursor_x = 0; + let mut cursor_y = 0; + let mut row_height = 0; + + let mut texels = vec![vec![' '; atlas_size]; atlas_size]; + let mut metadata = Vec::new(); + + for path in inputs { + let file = BufReader::new(File::open(&path).unwrap()); + let tex = file.lines().map(Result::unwrap).collect::<Vec<String>>(); + let (width, height) = (tex[0].len(), tex.len()); + + if cursor_x + width > atlas_size { + cursor_y += row_height; + row_height = 0; + cursor_x = 0; + } + if cursor_y + height > atlas_size { + panic!("texture too big or atlas full") + } + row_height = row_height.max(atlas_size); + let texcoord = [cursor_x, cursor_y]; + + for (y, line) in tex.iter().enumerate() { + if line.is_empty() { + continue; + } + for (x, char) in line.chars().enumerate() { + texels[cursor_y + y][cursor_x + x] = char; + } + } + + metadata.push(( + texcoord, + path.file_stem().unwrap().to_str().unwrap().to_string(), + )); + + cursor_x += atlas_size; + } + + let mut atlas_out = BufWriter::new(File::create(atlas_out).unwrap()); + let mut atlas_meta_out = BufWriter::new(File::create(atlas_meta_out).unwrap()); + + for line in texels { + for char in line { + write!(atlas_out, "{char}").unwrap() + } + writeln!(atlas_out).unwrap(); + } + + for ([x, y], name) in metadata { + writeln!(atlas_meta_out, "{x},{y},{name}").unwrap(); + } +} diff --git a/light-client/tools/src/lib.rs b/light-client/tools/src/lib.rs new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/light-client/tools/src/lib.rs diff --git a/protocol.md b/protocol.md index 28626200..956663ba 100644 --- a/protocol.md +++ b/protocol.md @@ -20,9 +20,10 @@ The protocol schema is defined in [`protocol.ts`](./test-client/protocol.ts) -1. Connect to the server via ~~TCP (on port 27031) or~~ WebSocket (on - port 27032) and send/receive json on individual lines / text messages. -2. Wait for `init` packet. +1. Connect to the server via WebSocket (on port 27032 for plain HTTP or 443 with + SSL) and send/receive json in WebSocket "Text" messages. The binary protocol + uses "Binary" messages and is optional for servers and clients. +2. Wait for `init` packet and check version compatibiliy (see below). 3. Send the join packet with your username. 4. The server will send the current game state: - `data` once for setting important look-up tables @@ -42,6 +43,23 @@ Collisions are handled by the clients. Whenever to players collide the player with the greater PlayerID is responsible for updating their own momentum and sending a packet to update that of the other player. +## Binary Protocol + +Servers might also support the binary protocol. It uses +[Bincode](https://github.com/bincode-org/bincode) to encode packets. If a server +advertises bincode support with the `init` packet, you are free to use the +binary protocol. By default the server will send JSON. For every packet you +send, you can choose between bincode and JSON. After a client sent the first +Bincode packet, the server might start to reply using Bincode aswell. Bincoded +packets are sent with WebSocket "Binary" messages. + +## Protocol Versioning + +The `init` packet sends minor and major version numbers of the protocol is use +by the server. These are to be interpreted according to +[SemVer](https://semver.org/) for the JSON protocol. The binary protocol can not +be used if either minor or major version differs. + ## Movement Movement is handled mostly client-side. Therefore it is implemented three times: diff --git a/server/Cargo.toml b/server/Cargo.toml index da084855..929f806d 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -13,11 +13,12 @@ tokio = { version = "1.38.0", features = ["full"] } serde_json = "1.0.120" tokio-tungstenite = "0.23.1" futures-util = "0.3.30" -serde_yaml = "0.9.34+deprecated" +serde_yml = "0.0.10" rand = "0.9.0-alpha.1" shlex = "1.3.0" clap = { version = "4.5.8", features = ["derive"] } fake = "2.9.2" pollster = "0.3.0" +bincode = "2.0.0-rc.3" hurrycurry-protocol = { path = "protocol" } diff --git a/server/protocol/Cargo.toml b/server/protocol/Cargo.toml index 8fc63121..6c51c86d 100644 --- a/server/protocol/Cargo.toml +++ b/server/protocol/Cargo.toml @@ -6,4 +6,4 @@ edition = "2021" [dependencies] serde = { version = "1.0.204", features = ["derive"] } glam = { version = "0.28.0", features = ["serde"] } - +bincode = { version = "2.0.0-rc.3", features = ["serde", "derive"] } diff --git a/server/protocol/src/lib.rs b/server/protocol/src/lib.rs index 94bebf05..895af376 100644 --- a/server/protocol/src/lib.rs +++ b/server/protocol/src/lib.rs @@ -15,6 +15,10 @@ along with this program. If not, see <https://www.gnu.org/licenses/>. */ +use bincode::{ + config::{standard, Configuration, Limit, LittleEndian, Varint}, + Decode, Encode, +}; use glam::{IVec2, Vec2}; use serde::{Deserialize, Serialize}; use std::{ @@ -26,31 +30,44 @@ pub use glam; pub const VERSION: (u32, u32) = (1, 0); -#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub const BINCODE_CONFIG: Configuration<LittleEndian, Varint, Limit<4096>> = + standard().with_limit(); + +#[derive( + Debug, Clone, Copy, Serialize, Deserialize, Encode, Decode, PartialEq, Eq, PartialOrd, Ord, Hash, +)] #[serde(transparent)] pub struct PlayerID(pub i64); -#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive( + Debug, Clone, Copy, Serialize, Deserialize, Encode, Decode, PartialEq, Eq, PartialOrd, Ord, Hash, +)] #[serde(transparent)] pub struct ItemIndex(pub usize); -#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive( + Debug, Clone, Copy, Serialize, Deserialize, Encode, Decode, PartialEq, Eq, PartialOrd, Ord, Hash, +)] #[serde(transparent)] pub struct TileIndex(pub usize); -#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive( + Debug, Clone, Copy, Serialize, Deserialize, Encode, Decode, PartialEq, Eq, PartialOrd, Ord, Hash, +)] #[serde(transparent)] pub struct RecipeIndex(pub usize); -#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive( + Debug, Clone, Copy, Serialize, Deserialize, Encode, Decode, PartialEq, Eq, PartialOrd, Ord, Hash, +)] #[serde(transparent)] pub struct DemandIndex(pub usize); -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode)] pub struct MapMetadata { name: String, players: usize, difficulty: i32, } -#[derive(Debug, Clone, Serialize, Deserialize, Default)] +#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode, Default)] #[rustfmt::skip] pub struct ClientGamedata { pub item_names: Vec<String>, @@ -61,7 +78,7 @@ pub struct ClientGamedata { pub maps: HashMap<String, MapMetadata>, } -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode)] #[serde(rename_all = "snake_case", tag = "type")] pub enum PacketS { Join { @@ -70,15 +87,18 @@ pub enum PacketS { }, Leave, Position { + #[bincode(with_serde)] pos: Vec2, rot: f32, boosting: bool, }, Interact { + #[bincode(with_serde)] pos: Option<IVec2>, }, Collide { player: PlayerID, + #[bincode(with_serde)] force: Vec2, }, Communicate { @@ -87,6 +107,7 @@ pub enum PacketS { }, #[serde(skip)] + #[bincode(skip)] /// For internal use only ReplaceHand { item: Option<ItemIndex>, @@ -97,7 +118,7 @@ pub enum PacketS { }, } -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode)] #[serde(rename_all = "snake_case")] pub enum Message { Text(String), @@ -105,12 +126,13 @@ pub enum Message { Effect(String), } -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode)] #[serde(rename_all = "snake_case", tag = "type")] pub enum PacketC { Version { minor: u32, major: u32, + supports_bincode: bool, }, Init { id: PlayerID, @@ -120,6 +142,7 @@ pub enum PacketC { }, AddPlayer { id: PlayerID, + #[bincode(with_serde)] position: Vec2, character: i32, name: String, @@ -129,6 +152,7 @@ pub enum PacketC { }, Position { player: PlayerID, + #[bincode(with_serde)] pos: Vec2, rot: f32, boosting: bool, @@ -147,12 +171,14 @@ pub enum PacketC { warn: bool, }, UpdateMap { + #[bincode(with_serde)] tile: IVec2, kind: Option<TileIndex>, neighbors: [Option<TileIndex>; 4], }, Collide { player: PlayerID, + #[bincode(with_serde)] force: Vec2, }, Communicate { @@ -181,10 +207,10 @@ pub enum PacketC { ReplayStart, } -#[derive(Debug, Clone, Serialize, Deserialize, Copy, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode, Copy, PartialEq, Eq, Hash)] #[serde(rename_all = "snake_case")] pub enum ItemLocation { - Tile(IVec2), + Tile(#[bincode(with_serde)] IVec2), Player(PlayerID), } diff --git a/server/src/data/mod.rs b/server/src/data/mod.rs index 0f1976b9..28347a25 100644 --- a/server/src/data/mod.rs +++ b/server/src/data/mod.rs @@ -136,7 +136,7 @@ fn data_dir() -> PathBuf { impl DataIndex { pub fn reload(&mut self) -> Result<()> { - *self = serde_yaml::from_reader(File::open(data_dir().join("index.yaml"))?)?; + *self = serde_yml::from_reader(File::open(data_dir().join("index.yaml"))?)?; Ok(()) } @@ -165,8 +165,8 @@ impl DataIndex { pub async fn generate(&self, spec: String) -> Result<Gamedata> { let (map, recipes) = spec.split_once("-").unwrap_or((spec.as_str(), "default")); - let map_in = serde_yaml::from_str(&self.read_map(map).await?)?; - let recipes_in = serde_yaml::from_str(&self.read_recipes(recipes).await?)?; + let map_in = serde_yml::from_str(&self.read_map(map).await?)?; + let recipes_in = serde_yml::from_str(&self.read_recipes(recipes).await?)?; let mut gd = Gamedata::build(spec, map_in, recipes_in)?; gd.map = self.maps.clone(); diff --git a/server/src/main.rs b/server/src/main.rs index 90d090d8..6f73851a 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -18,10 +18,19 @@ use anyhow::{anyhow, Result}; use clap::Parser; use futures_util::{SinkExt, StreamExt}; -use hurrycurry_protocol::{PacketC, PacketS, PlayerID, VERSION}; +use hurrycurry_protocol::{PacketC, PacketS, PlayerID, BINCODE_CONFIG, VERSION}; use hurrycurry_server::{data::DATA_DIR, state::State}; use log::{debug, info, trace, warn, LevelFilter}; -use std::{path::PathBuf, process::exit, str::FromStr, sync::Arc, time::Duration}; +use std::{ + path::PathBuf, + process::exit, + str::FromStr, + sync::{ + atomic::{AtomicBool, Ordering}, + Arc, + }, + time::Duration, +}; use tokio::{ net::TcpListener, spawn, @@ -121,9 +130,14 @@ async fn run() -> anyhow::Result<()> { PacketC::Version { major: VERSION.0, minor: VERSION.1, + supports_bincode: true, }, ); init.insert(1, PacketC::Init { id }); + + let supports_binary = Arc::new(AtomicBool::new(false)); + let supports_binary2 = supports_binary.clone(); + spawn(async move { for p in init { if let Err(e) = write @@ -154,52 +168,62 @@ async fn run() -> anyhow::Result<()> { info!("client outbound sender dropped. closing connection"); break; }; - if let Err(e) = write - .send(tokio_tungstenite::tungstenite::Message::Text( - serde_json::to_string(&packet).unwrap(), - )) - .await - { + let message = if supports_binary.load(Ordering::Relaxed) { + Message::Binary(bincode::encode_to_vec(&packet, BINCODE_CONFIG).unwrap()) + } else { + Message::Text(serde_json::to_string(&packet).unwrap()) + }; + if let Err(e) = write.send(message).await { warn!("ws error: {e}"); break; } } }); + spawn(async move { info!("{id:?} joined"); while let Some(Ok(message)) = read.next().await { - match message { - Message::Text(line) => { - let packet = match serde_json::from_str(&line) { - Ok(p) => p, - Err(e) => { - warn!("invalid packet: {e}"); - break; - } - }; - if matches!( - packet, - PacketS::Position { .. } | PacketS::ReplayTick { .. } - ) { - trace!("<- {id:?} {packet:?}"); - } else { - debug!("<- {id:?} {packet:?}"); + let packet = match message { + Message::Text(line) => match serde_json::from_str(&line) { + Ok(p) => p, + Err(e) => { + warn!("invalid json packet: {e}"); + break; } - let packet_out = match state.write().await.packet_in(id, packet).await { - Ok(packets) => packets, + }, + Message::Binary(packet) => { + supports_binary2.store(true, Ordering::Relaxed); + match bincode::decode_from_slice::<PacketS, _>(&packet, BINCODE_CONFIG) { + Ok((p, _size)) => p, Err(e) => { - warn!("client error: {e}"); - vec![PacketC::Error { - message: format!("{e}"), - }] + warn!("invalid binary packet: {e}"); + break; } - }; - for packet in packet_out { - let _ = error_tx.send(packet).await; } } Message::Close(_) => break, - _ => (), + _ => continue, + }; + + if matches!( + packet, + PacketS::Position { .. } | PacketS::ReplayTick { .. } + ) { + trace!("<- {id:?} {packet:?}"); + } else { + debug!("<- {id:?} {packet:?}"); + } + let packet_out = match state.write().await.packet_in(id, packet).await { + Ok(packets) => packets, + Err(e) => { + warn!("client error: {e}"); + vec![PacketC::Error { + message: format!("{e}"), + }] + } + }; + for packet in packet_out { + let _ = error_tx.send(packet).await; } } info!("{id:?} left"); diff --git a/test-client/protocol.ts b/test-client/protocol.ts index 2cd58f75..f8241854 100644 --- a/test-client/protocol.ts +++ b/test-client/protocol.ts @@ -44,7 +44,7 @@ export type PacketS = | { type: "collide", player: PlayerID, force: Vec2 } // Apply force to another player as a result of a collision export type PacketC = - { type: "version", minor: number, major: number } // Sent once after connecting to ensure you client is compatible + { type: "version", minor: number, major: number, supports_bincode?: boolean } // Sent once after connecting to ensure you client is compatible | { type: "init", id: PlayerID } // You just connected. This is your id for this session. | { type: "data", data: Gamedata } // Game data was changed | { type: "add_player", id: PlayerID, name: string, position: Vec2, character: number } // Somebody else joined (or was already in the game) |