diff --git a/.direnv/flake-inputs/jshala3b279h5mwy9bha3spyj7xpw9wz-source b/.direnv/flake-inputs/jshala3b279h5mwy9bha3spyj7xpw9wz-source
new file mode 120000
index 0000000..aaf1829
--- /dev/null
+++ b/.direnv/flake-inputs/jshala3b279h5mwy9bha3spyj7xpw9wz-source
@@ -0,0 +1 @@
+/nix/store/jshala3b279h5mwy9bha3spyj7xpw9wz-source
\ No newline at end of file
diff --git a/.direnv/flake-inputs/l4vzqgc77gsph6x2gig9wr0rd292cf89-source b/.direnv/flake-inputs/l4vzqgc77gsph6x2gig9wr0rd292cf89-source
deleted file mode 120000
index 533f4c0..0000000
--- a/.direnv/flake-inputs/l4vzqgc77gsph6x2gig9wr0rd292cf89-source
+++ /dev/null
@@ -1 +0,0 @@
-/nix/store/l4vzqgc77gsph6x2gig9wr0rd292cf89-source
\ No newline at end of file
diff --git a/.direnv/flake-profile-a5d5b61aa8a61b7d9d765e1daf971a9a578f1cfa b/.direnv/flake-profile-a5d5b61aa8a61b7d9d765e1daf971a9a578f1cfa
index 8cc2655..ea05503 120000
--- a/.direnv/flake-profile-a5d5b61aa8a61b7d9d765e1daf971a9a578f1cfa
+++ b/.direnv/flake-profile-a5d5b61aa8a61b7d9d765e1daf971a9a578f1cfa
@@ -1 +1 @@
-/nix/store/fx0gg8d8kpy3f98ar4k04623spprw59m-nix-shell-env
\ No newline at end of file
+/nix/store/i5gxwab2lp8mnrw0742lvwzzs4vp63rv-nix-shell-env
\ No newline at end of file
diff --git a/.direnv/flake-profile-a5d5b61aa8a61b7d9d765e1daf971a9a578f1cfa.rc b/.direnv/flake-profile-a5d5b61aa8a61b7d9d765e1daf971a9a578f1cfa.rc
index eab7bb6..6b5e481 100644
--- a/.direnv/flake-profile-a5d5b61aa8a61b7d9d765e1daf971a9a578f1cfa.rc
+++ b/.direnv/flake-profile-a5d5b61aa8a61b7d9d765e1daf971a9a578f1cfa.rc
@@ -23,7 +23,7 @@ export CXX
CXX_FOR_TARGET='g++'
export CXX_FOR_TARGET
HOSTTYPE='x86_64'
-HOST_PATH='/nix/store/95k9rsn1zsw1yvir8mj824ldhf90i4qw-gcc-wrapper-14.3.0/bin:/nix/store/l19cddv64i52rhcwahif8sgyrd3mhiqb-binutils-wrapper-2.44/bin:/nix/store/ahxj2q2mrl9z2k77ahqsl9j4zxq1wf84-gnumake-4.4.1/bin:/nix/store/ahixbqp1sm5vwzc19hz30vxvbkh7scxd-rust-default-1.90.0/bin:/nix/store/cw0gfvxbi05kqy13b2acm1vpnghpy0ni-evcxr-0.21.1/bin:/nix/store/8ksax0a2mxglr5hlkj2dzl556jx7xqn5-coreutils-9.7/bin:/nix/store/l964krgbp613d5jxga2vy5qdssj7zfzj-findutils-4.10.0/bin:/nix/store/s2fvny566vls74p4qm9v3fdqd741fh3f-diffutils-3.12/bin:/nix/store/pmhkmqy0vxk47r6ndh0azybhf6gs6k25-gnused-4.9/bin:/nix/store/vlckk0vnmawq9wwh7ndkrwxlpv4h29yh-gnugrep-3.12/bin:/nix/store/03nvbw411p097h6yxjghc33rbcrjfb9d-gawk-5.3.2/bin:/nix/store/8av8pfs7bnyc6hqj764ns4z1fnr9bva1-gnutar-1.35/bin:/nix/store/8gsxxh82rf957ffbsk0q9670nhvl5lia-gzip-1.14/bin:/nix/store/6yjb3zdj448rm8qsmpiq3f67kvj5683a-bzip2-1.0.8-bin/bin:/nix/store/aqdvlkh0jdwkc22hh5vr9sl6qlw5ha74-gnumake-4.4.1/bin:/nix/store/q7sqwn7i6w2b67adw0bmix29pxg85x3w-bash-5.3p3/bin:/nix/store/856i1ajaci3kmmp15rifacfz3jvn5l3q-patch-2.8/bin:/nix/store/y9kgzp85ykrhd7l691w4djx121qygy68-xz-5.8.1-bin/bin:/nix/store/v40ijzz8p2fpk9ihjck3a1ncqaqfmn3c-file-5.45/bin'
+HOST_PATH='/nix/store/95k9rsn1zsw1yvir8mj824ldhf90i4qw-gcc-wrapper-14.3.0/bin:/nix/store/l19cddv64i52rhcwahif8sgyrd3mhiqb-binutils-wrapper-2.44/bin:/nix/store/ahxj2q2mrl9z2k77ahqsl9j4zxq1wf84-gnumake-4.4.1/bin:/nix/store/k6nn8yn9w98xm7ibw5f7bm4ljfygdika-rust-default-1.91.0-beta.4-2025-09-28/bin:/nix/store/cw0gfvxbi05kqy13b2acm1vpnghpy0ni-evcxr-0.21.1/bin:/nix/store/8ksax0a2mxglr5hlkj2dzl556jx7xqn5-coreutils-9.7/bin:/nix/store/l964krgbp613d5jxga2vy5qdssj7zfzj-findutils-4.10.0/bin:/nix/store/s2fvny566vls74p4qm9v3fdqd741fh3f-diffutils-3.12/bin:/nix/store/pmhkmqy0vxk47r6ndh0azybhf6gs6k25-gnused-4.9/bin:/nix/store/vlckk0vnmawq9wwh7ndkrwxlpv4h29yh-gnugrep-3.12/bin:/nix/store/03nvbw411p097h6yxjghc33rbcrjfb9d-gawk-5.3.2/bin:/nix/store/8av8pfs7bnyc6hqj764ns4z1fnr9bva1-gnutar-1.35/bin:/nix/store/8gsxxh82rf957ffbsk0q9670nhvl5lia-gzip-1.14/bin:/nix/store/6yjb3zdj448rm8qsmpiq3f67kvj5683a-bzip2-1.0.8-bin/bin:/nix/store/aqdvlkh0jdwkc22hh5vr9sl6qlw5ha74-gnumake-4.4.1/bin:/nix/store/q7sqwn7i6w2b67adw0bmix29pxg85x3w-bash-5.3p3/bin:/nix/store/856i1ajaci3kmmp15rifacfz3jvn5l3q-patch-2.8/bin:/nix/store/y9kgzp85ykrhd7l691w4djx121qygy68-xz-5.8.1-bin/bin:/nix/store/v40ijzz8p2fpk9ihjck3a1ncqaqfmn3c-file-5.45/bin'
export HOST_PATH
IFS='
'
@@ -53,7 +53,7 @@ NIX_CC_WRAPPER_TARGET_HOST_x86_64_unknown_linux_gnu='1'
export NIX_CC_WRAPPER_TARGET_HOST_x86_64_unknown_linux_gnu
NIX_CC_WRAPPER_TARGET_TARGET_x86_64_unknown_linux_gnu='1'
export NIX_CC_WRAPPER_TARGET_TARGET_x86_64_unknown_linux_gnu
-NIX_CFLAGS_COMPILE=' -frandom-seed=fx0gg8d8kp -isystem /nix/store/ahxj2q2mrl9z2k77ahqsl9j4zxq1wf84-gnumake-4.4.1/include -isystem /nix/store/ahxj2q2mrl9z2k77ahqsl9j4zxq1wf84-gnumake-4.4.1/include -isystem /nix/store/ahxj2q2mrl9z2k77ahqsl9j4zxq1wf84-gnumake-4.4.1/include -isystem /nix/store/ahxj2q2mrl9z2k77ahqsl9j4zxq1wf84-gnumake-4.4.1/include'
+NIX_CFLAGS_COMPILE=' -frandom-seed=i5gxwab2lp -isystem /nix/store/ahxj2q2mrl9z2k77ahqsl9j4zxq1wf84-gnumake-4.4.1/include -isystem /nix/store/ahxj2q2mrl9z2k77ahqsl9j4zxq1wf84-gnumake-4.4.1/include -isystem /nix/store/ahxj2q2mrl9z2k77ahqsl9j4zxq1wf84-gnumake-4.4.1/include -isystem /nix/store/ahxj2q2mrl9z2k77ahqsl9j4zxq1wf84-gnumake-4.4.1/include'
export NIX_CFLAGS_COMPILE
NIX_CFLAGS_COMPILE_FOR_TARGET=' -isystem /nix/store/ahxj2q2mrl9z2k77ahqsl9j4zxq1wf84-gnumake-4.4.1/include'
export NIX_CFLAGS_COMPILE_FOR_TARGET
@@ -61,9 +61,9 @@ NIX_ENFORCE_NO_NATIVE='1'
export NIX_ENFORCE_NO_NATIVE
NIX_HARDENING_ENABLE='bindnow format fortify fortify3 pic relro stackclashprotection stackprotector strictoverflow zerocallusedregs'
export NIX_HARDENING_ENABLE
-NIX_LDFLAGS='-rpath /mnt/removable/Projects/Rust/multiplayer-game/outputs/out/lib -L/nix/store/ahixbqp1sm5vwzc19hz30vxvbkh7scxd-rust-default-1.90.0/lib -L/nix/store/ahixbqp1sm5vwzc19hz30vxvbkh7scxd-rust-default-1.90.0/lib -L/nix/store/ahixbqp1sm5vwzc19hz30vxvbkh7scxd-rust-default-1.90.0/lib -L/nix/store/ahixbqp1sm5vwzc19hz30vxvbkh7scxd-rust-default-1.90.0/lib'
+NIX_LDFLAGS='-rpath /mnt/removable/Projects/Rust/multiplayer-game/outputs/out/lib -L/nix/store/k6nn8yn9w98xm7ibw5f7bm4ljfygdika-rust-default-1.91.0-beta.4-2025-09-28/lib -L/nix/store/k6nn8yn9w98xm7ibw5f7bm4ljfygdika-rust-default-1.91.0-beta.4-2025-09-28/lib -L/nix/store/k6nn8yn9w98xm7ibw5f7bm4ljfygdika-rust-default-1.91.0-beta.4-2025-09-28/lib -L/nix/store/k6nn8yn9w98xm7ibw5f7bm4ljfygdika-rust-default-1.91.0-beta.4-2025-09-28/lib'
export NIX_LDFLAGS
-NIX_LDFLAGS_FOR_TARGET=' -L/nix/store/ahixbqp1sm5vwzc19hz30vxvbkh7scxd-rust-default-1.90.0/lib'
+NIX_LDFLAGS_FOR_TARGET=' -L/nix/store/k6nn8yn9w98xm7ibw5f7bm4ljfygdika-rust-default-1.91.0-beta.4-2025-09-28/lib'
export NIX_LDFLAGS_FOR_TARGET
NIX_NO_SELF_RPATH='1'
NIX_STORE='/nix/store'
@@ -84,7 +84,7 @@ OLDPWD=''
export OLDPWD
OPTERR='1'
OSTYPE='linux-gnu'
-PATH='/nix/store/gx2l0rnp3qcnysdddkg9dqnh2mz6w08k-patchelf-0.15.2/bin:/nix/store/95k9rsn1zsw1yvir8mj824ldhf90i4qw-gcc-wrapper-14.3.0/bin:/nix/store/82kmz7r96navanrc2fgckh2bamiqrgsw-gcc-14.3.0/bin:/nix/store/4jxivbjpr86wmsziqlf7iljlwjlxz8bh-glibc-2.40-66-bin/bin:/nix/store/8ksax0a2mxglr5hlkj2dzl556jx7xqn5-coreutils-9.7/bin:/nix/store/l19cddv64i52rhcwahif8sgyrd3mhiqb-binutils-wrapper-2.44/bin:/nix/store/c43ry7z24x3jhnjlj4gpay8a4g2p3x1h-binutils-2.44/bin:/nix/store/ahxj2q2mrl9z2k77ahqsl9j4zxq1wf84-gnumake-4.4.1/bin:/nix/store/ahixbqp1sm5vwzc19hz30vxvbkh7scxd-rust-default-1.90.0/bin:/nix/store/cw0gfvxbi05kqy13b2acm1vpnghpy0ni-evcxr-0.21.1/bin:/nix/store/8ksax0a2mxglr5hlkj2dzl556jx7xqn5-coreutils-9.7/bin:/nix/store/l964krgbp613d5jxga2vy5qdssj7zfzj-findutils-4.10.0/bin:/nix/store/s2fvny566vls74p4qm9v3fdqd741fh3f-diffutils-3.12/bin:/nix/store/pmhkmqy0vxk47r6ndh0azybhf6gs6k25-gnused-4.9/bin:/nix/store/vlckk0vnmawq9wwh7ndkrwxlpv4h29yh-gnugrep-3.12/bin:/nix/store/03nvbw411p097h6yxjghc33rbcrjfb9d-gawk-5.3.2/bin:/nix/store/8av8pfs7bnyc6hqj764ns4z1fnr9bva1-gnutar-1.35/bin:/nix/store/8gsxxh82rf957ffbsk0q9670nhvl5lia-gzip-1.14/bin:/nix/store/6yjb3zdj448rm8qsmpiq3f67kvj5683a-bzip2-1.0.8-bin/bin:/nix/store/aqdvlkh0jdwkc22hh5vr9sl6qlw5ha74-gnumake-4.4.1/bin:/nix/store/q7sqwn7i6w2b67adw0bmix29pxg85x3w-bash-5.3p3/bin:/nix/store/856i1ajaci3kmmp15rifacfz3jvn5l3q-patch-2.8/bin:/nix/store/y9kgzp85ykrhd7l691w4djx121qygy68-xz-5.8.1-bin/bin:/nix/store/v40ijzz8p2fpk9ihjck3a1ncqaqfmn3c-file-5.45/bin'
+PATH='/nix/store/gx2l0rnp3qcnysdddkg9dqnh2mz6w08k-patchelf-0.15.2/bin:/nix/store/95k9rsn1zsw1yvir8mj824ldhf90i4qw-gcc-wrapper-14.3.0/bin:/nix/store/82kmz7r96navanrc2fgckh2bamiqrgsw-gcc-14.3.0/bin:/nix/store/4jxivbjpr86wmsziqlf7iljlwjlxz8bh-glibc-2.40-66-bin/bin:/nix/store/8ksax0a2mxglr5hlkj2dzl556jx7xqn5-coreutils-9.7/bin:/nix/store/l19cddv64i52rhcwahif8sgyrd3mhiqb-binutils-wrapper-2.44/bin:/nix/store/c43ry7z24x3jhnjlj4gpay8a4g2p3x1h-binutils-2.44/bin:/nix/store/ahxj2q2mrl9z2k77ahqsl9j4zxq1wf84-gnumake-4.4.1/bin:/nix/store/k6nn8yn9w98xm7ibw5f7bm4ljfygdika-rust-default-1.91.0-beta.4-2025-09-28/bin:/nix/store/cw0gfvxbi05kqy13b2acm1vpnghpy0ni-evcxr-0.21.1/bin:/nix/store/8ksax0a2mxglr5hlkj2dzl556jx7xqn5-coreutils-9.7/bin:/nix/store/l964krgbp613d5jxga2vy5qdssj7zfzj-findutils-4.10.0/bin:/nix/store/s2fvny566vls74p4qm9v3fdqd741fh3f-diffutils-3.12/bin:/nix/store/pmhkmqy0vxk47r6ndh0azybhf6gs6k25-gnused-4.9/bin:/nix/store/vlckk0vnmawq9wwh7ndkrwxlpv4h29yh-gnugrep-3.12/bin:/nix/store/03nvbw411p097h6yxjghc33rbcrjfb9d-gawk-5.3.2/bin:/nix/store/8av8pfs7bnyc6hqj764ns4z1fnr9bva1-gnutar-1.35/bin:/nix/store/8gsxxh82rf957ffbsk0q9670nhvl5lia-gzip-1.14/bin:/nix/store/6yjb3zdj448rm8qsmpiq3f67kvj5683a-bzip2-1.0.8-bin/bin:/nix/store/aqdvlkh0jdwkc22hh5vr9sl6qlw5ha74-gnumake-4.4.1/bin:/nix/store/q7sqwn7i6w2b67adw0bmix29pxg85x3w-bash-5.3p3/bin:/nix/store/856i1ajaci3kmmp15rifacfz3jvn5l3q-patch-2.8/bin:/nix/store/y9kgzp85ykrhd7l691w4djx121qygy68-xz-5.8.1-bin/bin:/nix/store/v40ijzz8p2fpk9ihjck3a1ncqaqfmn3c-file-5.45/bin'
export PATH
PS4='+ '
RANLIB='ranlib'
@@ -116,7 +116,7 @@ export XDG_DATA_DIRS
__structuredAttrs=''
export __structuredAttrs
_substituteStream_has_warned_replace_deprecation='false'
-buildInputs='/nix/store/95k9rsn1zsw1yvir8mj824ldhf90i4qw-gcc-wrapper-14.3.0 /nix/store/ahxj2q2mrl9z2k77ahqsl9j4zxq1wf84-gnumake-4.4.1 /nix/store/ahixbqp1sm5vwzc19hz30vxvbkh7scxd-rust-default-1.90.0 /nix/store/cw0gfvxbi05kqy13b2acm1vpnghpy0ni-evcxr-0.21.1'
+buildInputs='/nix/store/95k9rsn1zsw1yvir8mj824ldhf90i4qw-gcc-wrapper-14.3.0 /nix/store/ahxj2q2mrl9z2k77ahqsl9j4zxq1wf84-gnumake-4.4.1 /nix/store/k6nn8yn9w98xm7ibw5f7bm4ljfygdika-rust-default-1.91.0-beta.4-2025-09-28 /nix/store/cw0gfvxbi05kqy13b2acm1vpnghpy0ni-evcxr-0.21.1'
export buildInputs
buildPhase='{ echo "------------------------------------------------------------";
echo " WARNING: the existence of this path is not guaranteed.";
@@ -165,7 +165,6 @@ declare -a envHostHostHooks=('ccWrapper_addCVars' 'bintoolsWrapper_addLDVars' 'c
declare -a envHostTargetHooks=('ccWrapper_addCVars' 'bintoolsWrapper_addLDVars' 'ccWrapper_addCVars' 'bintoolsWrapper_addLDVars' )
declare -a envTargetTargetHooks=('ccWrapper_addCVars' 'bintoolsWrapper_addLDVars' )
declare -a fixupOutputHooks=('if [ -z "${dontPatchELF-}" ]; then patchELF "$prefix"; fi' 'if [[ -z "${noAuditTmpdir-}" && -e "$prefix" ]]; then auditTmpdir "$prefix"; fi' 'if [ -z "${dontGzipMan-}" ]; then compressManPages "$prefix"; fi' '_moveLib64' '_moveSbin' '_moveSystemdUserUnits' 'patchShebangsAuto' '_pruneLibtoolFiles' '_doStrip' )
-guess='16'
initialPath='/nix/store/8ksax0a2mxglr5hlkj2dzl556jx7xqn5-coreutils-9.7 /nix/store/l964krgbp613d5jxga2vy5qdssj7zfzj-findutils-4.10.0 /nix/store/s2fvny566vls74p4qm9v3fdqd741fh3f-diffutils-3.12 /nix/store/pmhkmqy0vxk47r6ndh0azybhf6gs6k25-gnused-4.9 /nix/store/vlckk0vnmawq9wwh7ndkrwxlpv4h29yh-gnugrep-3.12 /nix/store/03nvbw411p097h6yxjghc33rbcrjfb9d-gawk-5.3.2 /nix/store/8av8pfs7bnyc6hqj764ns4z1fnr9bva1-gnutar-1.35 /nix/store/8gsxxh82rf957ffbsk0q9670nhvl5lia-gzip-1.14 /nix/store/6yjb3zdj448rm8qsmpiq3f67kvj5683a-bzip2-1.0.8-bin /nix/store/aqdvlkh0jdwkc22hh5vr9sl6qlw5ha74-gnumake-4.4.1 /nix/store/q7sqwn7i6w2b67adw0bmix29pxg85x3w-bash-5.3p3 /nix/store/856i1ajaci3kmmp15rifacfz3jvn5l3q-patch-2.8 /nix/store/y9kgzp85ykrhd7l691w4djx121qygy68-xz-5.8.1-bin /nix/store/v40ijzz8p2fpk9ihjck3a1ncqaqfmn3c-file-5.45'
mesonFlags=''
export mesonFlags
@@ -195,7 +194,7 @@ declare -a pkgsBuildBuild=()
declare -a pkgsBuildHost=('/nix/store/gx2l0rnp3qcnysdddkg9dqnh2mz6w08k-patchelf-0.15.2' '/nix/store/jwjq0fjgn7d00kswhaw2m8hbgws5vbi4-update-autotools-gnu-config-scripts-hook' '/nix/store/0y5xmdb7qfvimjwbq7ibg1xdgkgjwqng-no-broken-symlinks.sh' '/nix/store/cv1d7p48379km6a85h4zp6kr86brh32q-audit-tmpdir.sh' '/nix/store/85clx3b0xkdf58jn161iy80y5223ilbi-compress-man-pages.sh' '/nix/store/wgrbkkaldkrlrni33ccvm3b6vbxzb656-make-symlinks-relative.sh' '/nix/store/5yzw0vhkyszf2d179m0qfkgxmp5wjjx4-move-docs.sh' '/nix/store/fyaryjvghbkpfnsyw97hb3lyb37s1pd6-move-lib64.sh' '/nix/store/kd4xwxjpjxi71jkm6ka0np72if9rm3y0-move-sbin.sh' '/nix/store/pag6l61paj1dc9sv15l7bm5c17xn5kyk-move-systemd-user-units.sh' '/nix/store/cmzya9irvxzlkh7lfy6i82gbp0saxqj3-multiple-outputs.sh' '/nix/store/x8c40nfigps493a07sdr2pm5s9j1cdc0-patch-shebangs.sh' '/nix/store/cickvswrvann041nqxb0rxilc46svw1n-prune-libtool-files.sh' '/nix/store/xyff06pkhki3qy1ls77w10s0v79c9il0-reproducible-builds.sh' '/nix/store/z7k98578dfzi6l3hsvbivzm7hfqlk0zc-set-source-date-epoch-to-latest.sh' '/nix/store/pilsssjjdxvdphlg2h19p0bfx5q0jzkn-strip.sh' '/nix/store/95k9rsn1zsw1yvir8mj824ldhf90i4qw-gcc-wrapper-14.3.0' '/nix/store/l19cddv64i52rhcwahif8sgyrd3mhiqb-binutils-wrapper-2.44' )
declare -a pkgsBuildTarget=()
declare -a pkgsHostHost=('/nix/store/95k9rsn1zsw1yvir8mj824ldhf90i4qw-gcc-wrapper-14.3.0' '/nix/store/l19cddv64i52rhcwahif8sgyrd3mhiqb-binutils-wrapper-2.44' )
-declare -a pkgsHostTarget=('/nix/store/95k9rsn1zsw1yvir8mj824ldhf90i4qw-gcc-wrapper-14.3.0' '/nix/store/l19cddv64i52rhcwahif8sgyrd3mhiqb-binutils-wrapper-2.44' '/nix/store/ahxj2q2mrl9z2k77ahqsl9j4zxq1wf84-gnumake-4.4.1' '/nix/store/ahixbqp1sm5vwzc19hz30vxvbkh7scxd-rust-default-1.90.0' '/nix/store/cw0gfvxbi05kqy13b2acm1vpnghpy0ni-evcxr-0.21.1' )
+declare -a pkgsHostTarget=('/nix/store/95k9rsn1zsw1yvir8mj824ldhf90i4qw-gcc-wrapper-14.3.0' '/nix/store/l19cddv64i52rhcwahif8sgyrd3mhiqb-binutils-wrapper-2.44' '/nix/store/ahxj2q2mrl9z2k77ahqsl9j4zxq1wf84-gnumake-4.4.1' '/nix/store/k6nn8yn9w98xm7ibw5f7bm4ljfygdika-rust-default-1.91.0-beta.4-2025-09-28' '/nix/store/cw0gfvxbi05kqy13b2acm1vpnghpy0ni-evcxr-0.21.1' )
declare -a pkgsTargetTarget=()
declare -a postFixupHooks=('noBrokenSymlinksInAllOutputs' '_makeSymlinksRelativeInAllOutputs' '_multioutPropagateDev' )
declare -a postUnpackHooks=('_updateSourceDateEpochFromSourceRoot' )
diff --git a/flake.nix b/flake.nix
index ef403a2..67795f3 100644
--- a/flake.nix
+++ b/flake.nix
@@ -19,7 +19,7 @@
buildInputs = with pkgs; [
gcc
gnumake
- rust-bin.stable.latest.default
+ rust-bin.beta.latest.default
evcxr
];
};
diff --git a/public/index.html b/public/index.html
index 819b5a0..b39b585 100644
--- a/public/index.html
+++ b/public/index.html
@@ -1,30 +1,29 @@
-
+
-
-
-
- Hello World!
-
-
+
+
+
+ Hello World!
+
+
-
-
+
+
-
+
-
+
-
-
-
-
+
+
+
diff --git a/public/index.js b/public/index.js
index 58f68f1..48dd256 100644
--- a/public/index.js
+++ b/public/index.js
@@ -1,4 +1,4 @@
-const socket = new WebSocket("ws://localhost:8080/websocket");
+const socket = new WebSocket("/websocket");
socket.addEventListener("message", (event) => {
let messages = document.getElementById("messages");
diff --git a/src/content_type/any_content.rs b/src/content_type/any_content.rs
new file mode 100644
index 0000000..bd3216c
--- /dev/null
+++ b/src/content_type/any_content.rs
@@ -0,0 +1,77 @@
+use std::str::FromStr;
+
+use crate::content_type::{
+ any_content_type::ContentType, invalid_data_error, parameters::parameters::Parameter,
+};
+
+#[derive(Debug, PartialEq)]
+pub struct Content {
+ pub content_type: Option,
+ pub parameter: Option>,
+}
+
+impl Content {
+ pub fn is_text(&self) -> bool {
+ self.content_type.is_none()
+ || matches!(self.content_type.as_ref().unwrap(), ContentType::Text(_))
+ }
+
+ pub fn is_application(&self) -> bool {
+ self.content_type.is_none()
+ || matches!(
+ self.content_type.as_ref().unwrap(),
+ ContentType::Application(_)
+ )
+ }
+
+ pub fn quality(&self) -> Option {
+ self.parameter.as_ref()?.iter().find_map(|p| {
+ if let Parameter::Preference(q) = p {
+ Some(*q)
+ } else {
+ None
+ }
+ })
+ }
+
+ pub fn is_image(&self) -> bool {
+ self.content_type.is_none()
+ || matches!(self.content_type.as_ref().unwrap(), ContentType::Image(_))
+ }
+}
+
+impl FromStr for Content {
+ type Err = std::io::Error;
+
+ fn from_str(s: &str) -> Result {
+ match s.split(';').collect::>().as_slice() {
+ ["*/*", params @ ..] => Ok(Self {
+ content_type: None,
+ parameter: if s.is_empty() {
+ None
+ } else {
+ Some(
+ params
+ .iter()
+ .map(|v| Parameter::from_str(v))
+ .collect::>()?,
+ )
+ },
+ }),
+ [val, params @ ..] => Ok(Self {
+ content_type: Some(ContentType::from_str(val)?),
+ parameter: if s.is_empty() {
+ None
+ } else {
+ Some(
+ params
+ .iter()
+ .map(|v| Parameter::from_str(v))
+ .collect::>()?,
+ )
+ },
+ }),
+ _ => Err(invalid_data_error("Invalid content-type")),
+ }
+ }
+}
diff --git a/src/content_type/any_content_type.rs b/src/content_type/any_content_type.rs
new file mode 100644
index 0000000..232db79
--- /dev/null
+++ b/src/content_type/any_content_type.rs
@@ -0,0 +1,50 @@
+use std::str::FromStr;
+
+use crate::content_type::{
+ invalid_data_error,
+ types::{application::ApplicationType, image::Image, text::TextType},
+};
+
+#[derive(Debug, PartialEq)]
+pub enum ContentType {
+ Text(Option),
+ Application(Option),
+ Image(Option),
+ Any,
+}
+
+impl FromStr for ContentType {
+ type Err = std::io::Error;
+
+ fn from_str(s: &str) -> Result {
+ let parts: Vec<&str> = s.split('/').collect();
+
+ match parts.as_slice() {
+ ["text", "html"] => Ok(Self::Text(Some(TextType::Html))),
+ ["text", "css"] => Ok(Self::Text(Some(TextType::Css))),
+ ["text", "javascript"] => Ok(Self::Text(Some(TextType::Javascript))),
+ ["text", "*"] => Ok(Self::Text(None)),
+
+ ["application", "json"] => Ok(Self::Application(Some(ApplicationType::Json))),
+ ["application", "xhtml+xml"] => Ok(Self::Application(Some(ApplicationType::XhtmlXml))),
+ ["application", "xml"] => Ok(Self::Application(Some(ApplicationType::Xml))),
+ ["application", "signed-exchange"] => {
+ Ok(Self::Application(Some(ApplicationType::SignedExchange)))
+ }
+ ["application", "*"] => Ok(Self::Application(None)),
+
+ ["image", "png"] => Ok(Self::Image(Some(Image::Png))),
+ ["image", "apng"] => Ok(Self::Image(Some(Image::Png))),
+ ["image", "jpeg"] | ["image", "jpg"] => Ok(Self::Image(Some(Image::Jpeg))),
+ ["image", "avif"] => Ok(Self::Image(Some(Image::Avif))),
+ ["image", "webp"] => Ok(Self::Image(Some(Image::Webp))),
+ ["image", "svg"] | ["image", "svg+xml"] => Ok(Self::Image(Some(Image::Svg))),
+ ["image", "jxl"] => Ok(Self::Image(Some(Image::JpegXL))),
+ ["image", "*"] => Ok(Self::Image(None)),
+
+ ["*", "*"] => Ok(Self::Any),
+
+ _ => Err(invalid_data_error("Invalid content-type-type")),
+ }
+ }
+}
diff --git a/src/content_type/content.rs b/src/content_type/content.rs
new file mode 100644
index 0000000..b8849cf
--- /dev/null
+++ b/src/content_type/content.rs
@@ -0,0 +1,76 @@
+use crate::content_type::{content_type::ContentType, parameters::parameters::Parameter};
+
+#[derive(Debug, PartialEq)]
+pub struct Content {
+ pub content_type: ContentType,
+ pub parameter: Option>,
+}
+
+impl Content {
+ pub fn new(content_type: ContentType) -> Self {
+ Self {
+ content_type,
+ parameter: None,
+ }
+ }
+
+ pub fn with_params(content_type: ContentType, params: Vec) -> Self {
+ Self {
+ content_type,
+ parameter: Some(params),
+ }
+ }
+
+ pub fn add_parameter(&mut self, param: Parameter) {
+ match &mut self.parameter {
+ Some(params) => params.push(param),
+ None => self.parameter = Some(vec![param]),
+ }
+ }
+
+ pub fn charset(&self) -> Option<&crate::content_type::parameters::charset::Charset> {
+ self.parameter.as_ref()?.iter().find_map(|p| {
+ if let Parameter::Charset(cs) = p {
+ Some(cs)
+ } else {
+ None
+ }
+ })
+ }
+
+ pub fn html_utf8() -> Self {
+ use crate::content_type::parameters::charset::Charset;
+ use crate::content_type::types::text::TextType;
+
+ Self::with_params(
+ ContentType::Text(TextType::Html),
+ vec![Parameter::Charset(Charset::UTF8)],
+ )
+ }
+
+ pub fn json_utf8() -> Self {
+ use crate::content_type::parameters::charset::Charset;
+ use crate::content_type::types::application::ApplicationType;
+
+ Self::with_params(
+ ContentType::Aplication(ApplicationType::Json),
+ vec![Parameter::Charset(Charset::UTF8)],
+ )
+ }
+
+ pub fn to_str(&self) -> Box {
+ match &self.parameter {
+ Some(params) => format!(
+ "{}; {}",
+ self.content_type.to_str(),
+ params
+ .iter()
+ .map(|p| p.to_str())
+ .collect::>()
+ .join("; ")
+ )
+ .into(),
+ None => self.content_type.to_str(),
+ }
+ }
+}
diff --git a/src/content_type/content_type.rs b/src/content_type/content_type.rs
new file mode 100644
index 0000000..acd41f6
--- /dev/null
+++ b/src/content_type/content_type.rs
@@ -0,0 +1,54 @@
+use std::str::FromStr;
+
+use crate::content_type::{
+ invalid_data_error,
+ types::{application::ApplicationType, image::Image, text::TextType},
+};
+
+#[derive(Debug, PartialEq)]
+pub enum ContentType {
+ Text(TextType),
+ Aplication(ApplicationType),
+ Image(Image),
+}
+
+impl ContentType {
+ pub fn to_str(&self) -> Box {
+ match self {
+ ContentType::Text(text) => format!("text/{}", text.to_str()).into(),
+ ContentType::Aplication(app) => format!("application/{}", app.to_str()).into(),
+ ContentType::Image(img) => format!("image/{}", img.to_str()).into(),
+ }
+ }
+}
+
+impl FromStr for ContentType {
+ type Err = std::io::Error;
+
+ fn from_str(s: &str) -> Result {
+ let parts: Vec<&str> = s.split('/').collect();
+
+ match parts.as_slice() {
+ ["text", "html"] => Ok(Self::Text(TextType::Html)),
+ ["text", "css"] => Ok(Self::Text(TextType::Css)),
+ ["text", "javascript"] => Ok(Self::Text(TextType::Javascript)),
+
+ ["application", "json"] => Ok(Self::Aplication(ApplicationType::Json)),
+ ["application", "xhtml+xml"] => Ok(Self::Aplication(ApplicationType::XhtmlXml)),
+ ["application", "xml"] => Ok(Self::Aplication(ApplicationType::Xml)),
+ ["application", "signed-exchange"] => {
+ Ok(Self::Aplication(ApplicationType::SignedExchange))
+ }
+
+ ["image", "png"] => Ok(Self::Image(Image::Png)),
+ ["image", "apng"] => Ok(Self::Image(Image::Png)),
+ ["image", "jpeg"] | ["image", "jpg"] => Ok(Self::Image(Image::Jpeg)),
+ ["image", "avif"] => Ok(Self::Image(Image::Avif)),
+ ["image", "webp"] => Ok(Self::Image(Image::Webp)),
+ ["image", "svg"] | ["image", "svg+xml"] => Ok(Self::Image(Image::Svg)),
+ ["image", "jxl"] => Ok(Self::Image(Image::JpegXL)),
+
+ _ => Err(invalid_data_error("Invalid content-type-type")),
+ }
+ }
+}
diff --git a/src/content_type/mod.rs b/src/content_type/mod.rs
new file mode 100644
index 0000000..2faf7f2
--- /dev/null
+++ b/src/content_type/mod.rs
@@ -0,0 +1,12 @@
+pub mod any_content;
+pub mod any_content_type;
+pub mod content;
+pub mod content_type;
+pub mod parameters;
+pub mod types;
+
+use tokio::io;
+
+pub fn invalid_data_error(error: &str) -> io::Error {
+ io::Error::new(io::ErrorKind::InvalidData, error)
+}
diff --git a/src/content_type/parameters/charset.rs b/src/content_type/parameters/charset.rs
new file mode 100644
index 0000000..0044548
--- /dev/null
+++ b/src/content_type/parameters/charset.rs
@@ -0,0 +1,12 @@
+#[derive(Debug, PartialEq)]
+pub enum Charset {
+ UTF8,
+}
+
+impl Charset {
+ pub fn to_str(&self) -> &'static str {
+ match self {
+ Charset::UTF8 => "utf-8",
+ }
+ }
+}
diff --git a/src/content_type/parameters/mod.rs b/src/content_type/parameters/mod.rs
new file mode 100644
index 0000000..0a06b34
--- /dev/null
+++ b/src/content_type/parameters/mod.rs
@@ -0,0 +1,3 @@
+pub mod parameters;
+pub mod charset;
+
diff --git a/src/content_type/parameters/parameters.rs b/src/content_type/parameters/parameters.rs
new file mode 100644
index 0000000..e3b14c0
--- /dev/null
+++ b/src/content_type/parameters/parameters.rs
@@ -0,0 +1,37 @@
+use crate::content_type::parameters::charset::Charset;
+use crate::content_type::invalid_data_error;
+
+use std::str::FromStr;
+
+#[derive(Debug, PartialEq)]
+pub enum Parameter {
+ Preference(f32),
+ Charset(Charset),
+ Other(Box, Box),
+}
+
+impl Parameter {
+ pub fn to_str(&self) -> Box {
+ match self {
+ Parameter::Preference(val) => format!("q={val}").into(),
+ Parameter::Charset(ch) => format!("charset={}", ch.to_str()).into(),
+ Parameter::Other(p, v) => format!("{p}={v}").into(),
+ }
+ }
+}
+
+impl FromStr for Parameter {
+ type Err = std::io::Error;
+
+ fn from_str(s: &str) -> Result {
+ match s.split('=').collect::>().as_slice() {
+ ["q", val] => Ok(Self::Preference(
+ val.parse::().map_err(|_| invalid_data_error("Invalid preference"))?,
+ )),
+ ["charset", "utf-8"] => Ok(Self::Charset(Charset::UTF8)),
+ [name, val] => Ok(Self::Other((*name).into(), (*val).into())),
+ _ => Err(invalid_data_error("Invalid parameter")),
+ }
+ }
+}
+
diff --git a/src/content_type/types/application.rs b/src/content_type/types/application.rs
new file mode 100644
index 0000000..e2cefa0
--- /dev/null
+++ b/src/content_type/types/application.rs
@@ -0,0 +1,19 @@
+#[derive(Debug, PartialEq)]
+pub enum ApplicationType {
+ Json,
+ XhtmlXml,
+ Xml,
+ SignedExchange,
+}
+
+impl ApplicationType {
+ pub fn to_str(&self) -> &'static str {
+ match self {
+ ApplicationType::Json => "json",
+ ApplicationType::XhtmlXml => "xhtml+xml",
+ ApplicationType::Xml => "xml",
+ ApplicationType::SignedExchange => "signed-exchange",
+ }
+ }
+}
+
diff --git a/src/content_type/types/image.rs b/src/content_type/types/image.rs
new file mode 100644
index 0000000..90116c4
--- /dev/null
+++ b/src/content_type/types/image.rs
@@ -0,0 +1,23 @@
+#[derive(Debug, PartialEq)]
+pub enum Image {
+ Png,
+ Avif,
+ Jpeg,
+ Webp,
+ Svg,
+ JpegXL,
+}
+
+impl Image {
+ pub fn to_str(&self) -> &'static str {
+ match self {
+ Image::Png => "png",
+ Image::Avif => "avif",
+ Image::Jpeg => "jpeg",
+ Image::Webp => "webp",
+ Image::Svg => "svg",
+ Image::JpegXL => "jxl",
+ }
+ }
+}
+
diff --git a/src/content_type/types/mod.rs b/src/content_type/types/mod.rs
new file mode 100644
index 0000000..6305888
--- /dev/null
+++ b/src/content_type/types/mod.rs
@@ -0,0 +1,4 @@
+pub mod text;
+pub mod application;
+pub mod image;
+
diff --git a/src/content_type/types/text.rs b/src/content_type/types/text.rs
new file mode 100644
index 0000000..5f9e1b0
--- /dev/null
+++ b/src/content_type/types/text.rs
@@ -0,0 +1,17 @@
+#[derive(Debug, PartialEq)]
+pub enum TextType {
+ Html,
+ Css,
+ Javascript,
+}
+
+impl TextType {
+ pub fn to_str(&self) -> &'static str {
+ match self {
+ TextType::Html => "html",
+ TextType::Css => "css",
+ TextType::Javascript => "javascript",
+ }
+ }
+}
+
diff --git a/src/game_manager.rs b/src/game_manager.rs
new file mode 100644
index 0000000..01b5aff
--- /dev/null
+++ b/src/game_manager.rs
@@ -0,0 +1,59 @@
+use tokio::sync::mpsc;
+
+pub enum ServerMessage {}
+
+pub enum ClientMessage {}
+
+struct Player {
+ receiver: mpsc::Receiver,
+ sender: mpsc::Sender,
+
+ intended_move: Option,
+}
+
+enum Move {
+ Move { start: (u8, u8), end: (u8, u8) },
+ Attack,
+}
+
+pub struct GameManager {
+ player_1: Player,
+ player_2: Player,
+}
+
+impl GameManager {
+ pub fn new(
+ p1r: mpsc::Receiver,
+ p1s: mpsc::Sender,
+
+ p2r: mpsc::Receiver,
+ p2s: mpsc::Sender,
+ ) -> Self {
+ Self {
+ player_1: Player {
+ receiver: p1r,
+ sender: p1s,
+ intended_move: None,
+ },
+ player_2: Player {
+ receiver: p2r,
+ sender: p2s,
+ intended_move: None,
+ },
+ }
+ }
+
+ pub async fn run(&mut self) {
+ loop {
+ tokio::select! {
+ p1_action = self.player_1.receiver.recv() => {
+
+ }
+
+ p2_action = self.player_2.receiver.recv() => {
+
+ }
+ }
+ }
+ }
+}
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..93474a8
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,6 @@
+pub mod content_type;
+pub mod game_manager;
+pub mod player_queue;
+pub mod request;
+pub mod response;
+pub mod websoket_connection;
diff --git a/src/main.rs b/src/main.rs
index 840e7a1..422f051 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,12 +1,11 @@
-mod request;
-mod response;
-mod shared_enums;
-mod websoket_connection;
+use multiplayer_game::request;
+use multiplayer_game::response;
+use multiplayer_game::websoket_connection;
use std::time::Duration;
use std::{path::Path, str::FromStr};
-use tokio::io::{self, AsyncWriteExt};
+use tokio::io::AsyncWriteExt;
use tokio::net::{TcpListener, TcpStream};
use tokio::time;
@@ -16,27 +15,19 @@ use crate::{
response::{Response, ResponseCode, ResponseHeader},
};
-use tokio::sync;
-
#[tokio::main]
async fn main() -> tokio::io::Result<()> {
- let listener = TcpListener::bind("127.0.0.1:8080").await?;
- let (sender, _) = sync::broadcast::channel(16);
+ let listener = TcpListener::bind("0.0.0.0:9123").await?;
+
loop {
let (stream, _) = listener.accept().await?;
- let receiver = sender.subscribe();
- let sender = sender.clone();
- tokio::spawn(handle_connection(stream, receiver, sender));
+ tokio::spawn(handle_connection(stream));
}
}
-async fn handle_connection(
- stream: TcpStream,
- receiver: sync::broadcast::Receiver,
- sender: sync::broadcast::Sender,
-) -> tokio::io::Result<()> {
+async fn handle_connection(stream: TcpStream) -> tokio::io::Result<()> {
if let Some(ws) = handle_http_connection(stream).await? {
- handle_websocket(ws, receiver, sender).await?
+ handle_websocket(ws).await?
}
Ok(())
@@ -45,17 +36,19 @@ async fn handle_connection(
async fn handle_http_connection(
mut stream: TcpStream,
) -> tokio::io::Result