From 84239feb4ab7a756b624ab39aea1d634ac99c9d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Rivi=C3=A8re?= Date: Sun, 18 May 2025 15:29:43 +0200 Subject: [PATCH] =?UTF-8?q?Am=C3=A9liorations=20mineures?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- traque-back/images/missing_image.jpg | Bin 0 -> 10227 bytes traque-back/photo.js | 10 +++--- traque-back/team_socket.js | 32 ++++++++++--------- traque-front/components/admin/mapPicker.jsx | 4 +-- traque-front/components/admin/teamAdd.jsx | 8 +++-- traque-front/components/admin/teamEdit.jsx | 2 +- traque-front/public/images/missing_image.jpg | Bin 0 -> 10227 bytes 7 files changed, 32 insertions(+), 24 deletions(-) create mode 100644 traque-back/images/missing_image.jpg create mode 100644 traque-front/public/images/missing_image.jpg diff --git a/traque-back/images/missing_image.jpg b/traque-back/images/missing_image.jpg new file mode 100644 index 0000000000000000000000000000000000000000..cba7e59ab21579d99261046e2ad8468faf78e080 GIT binary patch literal 10227 zcmeHM2|SeB-+#swB5Ddrmbv3zH;S>0Z5T@#QU;Tmv?*f@#xR)0mNKe)uO(CcZ;KR) zG8#*_B%yFilq|QTNs(lYP?iwoeV$QT?|r-f|NrxOKmYfAPtEh3<+q>jIp=pC(+{Sf z01MaJJK6&D3f^2$vE_ zQtFiwTY(9jQS~q+>t; zm(5{OICQXKM`P1{nW_>@K-q!D;Y1)E11Y{VHk$6n38FHBAv31ifJA&a-3I_19d!U{ z&b{4IM|-wD>C@^7$hB`6yb|NcGQHn-G|!wJTs(M+}; z#XHE0rbi75M2Ay?(FS_@Xu#4sJeWdd&^SmhnlGJ+Lk*Ucp^$WM9Ln98pic;1P4lC# ziDc2-BArRpNCws18)a=JV;PPO4-5{ZaVW^}zyKy28;(PXg=4`w)Qv`2$;`84dHZ13 z+u6UP0b4lKJ7dDa!t}z7^nzHvXajR|bF{u8+R#uJq|jwYFgcWPT_#%-5-}qKj60P@ z4;Ie>B$MJ5#O2^nsCR%%NgHCsqfsXtR8v4yxEFHpd(N zF@=~_>?#_CM84B2#=r~&931UQvr<5*dcF`o=wf(?1MW-r;e4Xsn>tG$%w+|LwR%(0 zv;bNljmcqyv<9H6ndk&N*-+p=$jiEn(G^yK|a4T0P9Zka^p}q;)u-n!Ulm1VTaD1U2)>@2GD#d0q6iamBwV# zbSb_pnwZI&%L&{b2wKGr#DQ3&FzHk+N?@=B)Xfg!vZyqiZ%~kL0ByFH3Jz1iMUI0) z2F?rU9~fz@9fd<7(3y0m?`%xJG7q6aREihcj^L>4y541t<0?lI-cA?4aW&qR5n@91oY-{|Pz%A1IR6<0#5kOVfN$UjNa_CTFt9{_ z;sj*NXTHx&$|qFf{YyM`A8laJz9{YkH%4&!(X%@#*qGgmX-sef4g+`E=||wnAtNOv zEhQ-38Ad1@x%8h4b*p9D@@T^+8FKcQ2Mq87;_6NE2|&$ z>>O8Ht}(?~SwKQyGP1Jra`LJR7pht;M=iJb+hw{OKuE)KBsRif2tWb>gCk(m6@UtO z5(9AX_o2*%!RJUyfMd9YFaRb2hfB%A=SWDvAqucLXD&kVJKIGD7@`~N;9``a(RvCs z=e@x6Lts7}1{wuN0M@{(^3S;b zPc{wb!>Vll3D3QiC2ca3g(=!`$9iL>JaY0C!=h2k`NiFD;1}+%W16-U8N0k1kP6Jv zQm>&i8x02Wb~S+!s(~ShuEtUfiN*WdI<5MfN*a1(#C)wxh-K1k_!Ps0{Qg*S+uko6BzlA=$6<9eb(kkkW{X^|i zaMBLMG{C=SH(HNf5qba;Z?&R?+05|ZG^kHV{m}eKE{MCBd~1x!<4{5napwsw7*Q%V z<}whGLq4Y&U*sU2y^%!!cC*HqwYT%nDD|G}1p4z2d97&mAU)bYDMic4kh6b1L9QNc6 zRy|B0yXXir&-P`9>&rChwun~NOaoETzmf4U4fBFC57Bm!#9L`6bhN(FSoqEyb=1hj z5ka>_%p=AR!kvK+GO=e9pY-P+X$uS*iaOgTbmcT4oajz=4kY{C7eKM|oht0}4G~V0h9BGd1%Xcr< zTq9mM^{4!k#-0gRgvCNK$MZUs+Bf&b?_$ZXE4rle_`HKo$7G?6Szgz8d_e-Ifr)L8 z5}FNcFA3!qv4mwejmKv!sVinXzYUHIz&*J7OZs4e)7llD24n*dBd3>%ur57f$AEiK z)3Ki%%4ewm;t4Ilu*OHibBExU?h|9r?Yx!Q9R0vTm!=$v!!cb-IZ`yG+=q#}kK%W^ z#!o_mRG3e5Hr;2GIPJ)Y+7my(Wf~8ebe)SDhVut}<4bbzAx?tYkgKBpm9^dIF9Ad6@=~APkhW#!mU?V!JR< zR7-ahdZk1>O#4?3_6c)=Gu3v;GUF22KdidA>S+<{IwE~9XMC})*84HFR?3xarCG7 zkya*m8dxMP+&4q^)h8U&VC;OTqGr@ayx>cw(oopmX8A{(bT79?_LFy zV|8+)I#k|n4xiE9N}U^xu%a!yDlD|I2<#}JcR!Auuu=3bpm(*#jgf)&vX~0WXeTk( zpfcr!d@#f$)u>2VqMi5SPNPK&T$q=O@Wxe`%F^ZMPBN|rRX@mUt~%q)8#YosmK=Fl zc}B@so*JRgo3CPtOkt@j=$jSl^8JnmyYQQ{;3-Q|JJP?UKxIpMGPOn8>INvnSn~Mg z99-I_(4;X3GyaOA#;g|qX3^lWKfvw8lH77W zUZ2%13G%@lv`TJOxHCK&8*-w4rz_04(tH2nmaCcLsZPT0-wXcaT_f?c2d^N$z*LXC z;XIb0FLUI#BP%0Ii0Tuq$mV#E)c&n!l!%oOlFMyy+R*_{LV&T#4VC7!Fnw?f8tc8U z+d#NH!O-Db935yGJ*t!4jT8-iqygsgy3r#oYnUCGg`Uga3 z(l#)mieIAn*4SYh@EkdBV35N`U6510y=}`p7T+=@x&~e={7B%3s5NV5|D*Sd=!EC^uwRPEdkCS$EkrzQNKs^B#iuTN{D|u>exaYL1I%5gr zrdJ+Ofa%ldB%X#SJ};8Z#!dNgh3swqG0%$H!%VTu7bG;g6Owx~oJscQvn)rOnW$+% z5Sok4U}e~twB<$w5R@`~P-p*8G|^4HUj~Su(r~Y)e#Q&l|41Y7I_=U6QF{Lp#xee) zJr|+bQw`54-bZfL_NdNSa~Jg;QSi6Sle#N7kZ+HwHCX zbL~?Sd<)K910G!3v3Uw9CvL#5CsDMod88-%Cl`_WuBh@pk1_y^gfA=IBE`%zP+2P< z;~bte2CwzXjZh`ujzZ;DCnBHSe!VmG1#Zb^5Fvk6qyUGyt2^_aza=mJk_@)xhmzvX zV{NC)b<%l>Cz?7Q7lvAQs<_k=F>2<~F8Pn8();jVvVGJeufqFl4Gl+IhRmvU+Kg_c z9l$MGE^k>UI{Z7?(r-B9&2EVd0s7gi9pxh)ekaZH*NIkA&I%jZ1h=jB=Z6lgeW+ae z_{?fQugORrR6S|(GrBNK?o>j5FZ@5CGXu0!is_zE7QL9fM2|qaq4Lana?qCK#?$QH zRw@dO)`{bN6vubf8t3EfJe-Mo_mS(5it4K~jVDe%SfS{q*np|W3`iX3}*xH)9|F9pu_5N{QGL>Ep;+|@2e44>Q1D6u|lS3WyB zTY)jON~*7m{3Cj@-^Sn-c&lo2Sq4#8P2HW#I*HluXG;LM)J5v5jZdvX3H4`rzo8=nU*niJbIkni763_mzJRWgIt*EV2_}A&RL$+KJ7bZC)J?r;x{wj`ZP1 z9Y7SCN$g_Z@f)mqYODB_q;y#h1^x8LX+UkUfym;d+C}ez8iq$Nwe!l->>pB$GZ0So zWA?n6Y#_PkewzRLYyePTF^_KVp9X-7@xgPV`a};0>N|;Fb7?1W>!ZBn_S9o>QiAlX zym&_9OA?jLs=lAzlf0`@Uh&CqqMi%EDIi_+Ls1! zch_QWV20?4C^J<4P_tzIeJMFJuJqv~+WA|@Uuk!>k`3<7(}BYKtq}##H20`XnWT2R zT0?MyL-ZDO@j9)p$ z(?HPp+|z%(Ug5~5pG!JIl=^zJ)Q@_ERbdA4-pWbw7e#w}=f{*U9!^bg*k%1LXO>7M z{L<;Z0hQI_+#||SLfH7-py)o$tu-Dq>gWx@lY?R|XerSUY09fCH z*LRu4R(NI7Q~WZ`4RHQ^uoueoo^ju{zK~rb_^X2p0G7_(dSqbol24?NN5%ti-jCfl zCH~Z|?-67$bM{s++-H5L%+!CxuWMrWUGRv6ca?Bj3Nh{oOg*rwvU9Y}haspdv~0MS z)eb79{&<}g*tjdJbwe+=4HziN2Fu+y5D0;>SXG~Ws2G6 z>|?r{j28Vee74n47hvZIruk|Q&M%^@?s9h1OP5#f!^$mJcWTNdDNrbbe?Cz+)4K82?NdhGer&LJDB@b@Mh(<);p)TikPaO>%4(s3UWKZ5zqFf+yA&9{}M1s46#KN_gE| z(A7M(+xRy3VV+-}xv|4MQWVGzpP3Or#@uw>xmVKwZ!>tfSaJLM!+eLbk{|_N6xmJ2 zk2k1iZyrp~rFO_HKdB0{Ht)F@*8UP1pH&XjgijX#-V>}G-O#3;xl`xLGpV)jk}~=E z%uUXyh|r7aMQIj7Pqibt4d8zDtSb}t3e+K|oTHXQR&iHxVw0pdp7^0zH*#wtz0G|d z$#2$zxvIy{h$f@Ubx|i^8racSCHWI1r`geuD^g5y*e$Bpv6RND@0T33`2;lHY7tD0 z+fUoK+waGo+&(s%&ij}X{;k}lbH_Srq2)>s2 zpk=#C_!`YxVdf=rBU$B+3=b`=$aaouySFv*#P`Xggmy%Q1}lAS7sU;bnd5q|s303U7`AXY=} zh=ZW$$`7B|bC1|#V+DO+_`I0MRPDQ+`_zjes440XPD?_0gK58zy|Ka$l1Iw{b9jQ9iC#ppM*?SrrHpWaU4+^K|}=NnEam ztNONjhQq!26AZ9Hf~#+Cr8_hN^@j`l8`^>TL*VPF)XYa<^q zz`unkrE7U*r3?$^&1pHD@JjpjVL9=O*R-+BD=q7PXCo$2>|;#RktgTc&MUfyCdK=t zXgZGVPX6n=Ewq3ej*d*?o~(vU}w{Kg8w#Ykv{}*mTo>0R { let team = game.getTeam(Number(req.query.team)); + const imagePath = path.join(process.cwd(), UPLOAD_DIR, team.id.toString()); if (team) { res.set("Content-Type", "image/png") res.set("Access-Control-Allow-Origin", "*"); - res.sendFile(process.cwd() + "/" + UPLOAD_DIR + "/" + team.id); + res.sendFile(fs.existsSync(imagePath) ? imagePath : path.join(process.cwd(), "images", "missing_image.jpg")); } else { - res.send(400, "Team not found") + res.status(400).send("Team not found") } }) //App handler for serving the photo of the team chased by the team given by its secret ID app.get("/photo/enemy", (req, res) => { let team = game.getTeam(Number(req.query.team)); + const imagePath = path.join(process.cwd(), UPLOAD_DIR, team.chasing.toString()); if (team) { res.set("Content-Type", "image/png") res.set("Access-Control-Allow-Origin", "*"); - res.sendFile(process.cwd() + "/" + UPLOAD_DIR + "/" + team.chasing); + res.sendFile(fs.existsSync(imagePath) ? imagePath : path.join(process.cwd(), "images", "missing_image.jpg")); } else { - res.send(400, "Team not found") + res.status(400).send("Team not found") } }) } \ No newline at end of file diff --git a/traque-back/team_socket.js b/traque-back/team_socket.js index b8ef61f..d383a54 100644 --- a/traque-back/team_socket.js +++ b/traque-back/team_socket.js @@ -73,24 +73,26 @@ export function initTeamSocket() { logoutPlayer(socket.id) }); - socket.on("login", (loginTeamId) => { + socket.on("login", (loginTeamId, callback) => { if (game.getTeam(loginTeamId) === undefined) { socket.emit("login_response", false); - return; + callback({ isLoggedIn : false, message: "Login denied"}); + } else { + logoutPlayer(socket.id) + teamId = loginTeamId; + let team = game.getTeam(loginTeamId); + team.sockets.push(socket.id); + sendUpdatedTeamInformations(loginTeamId); + socket.emit("login_response", true); + socket.emit("game_state", game.state) + socket.emit("game_settings", game.settings) + socket.emit("zone", zone.currentZone) + socket.emit("new_zone", { + begin: zone.currentStartZone, + end: zone.nextZone + }) + callback({ isLoggedIn : true, message: "Logged in"}); } - logoutPlayer(socket.id) - teamId = loginTeamId; - let team = game.getTeam(loginTeamId); - team.sockets.push(socket.id); - sendUpdatedTeamInformations(loginTeamId); - socket.emit("login_response", true); - socket.emit("game_state", game.state) - socket.emit("game_settings", game.settings) - socket.emit("zone", zone.currentZone) - socket.emit("new_zone", { - begin: zone.currentStartZone, - end: zone.nextZone - }) }); socket.on("logout", () => { diff --git a/traque-front/components/admin/mapPicker.jsx b/traque-front/components/admin/mapPicker.jsx index c9d7993..6d58c30 100644 --- a/traque-front/components/admin/mapPicker.jsx +++ b/traque-front/components/admin/mapPicker.jsx @@ -41,7 +41,7 @@ export function CircularAreaPicker({ area, setArea, markerPosition, ...props }) const location = useLocation(Infinity); const { handleClick, handleMouseMove, center, radius } = useMapCircleDraw(area, setArea); return ( - +
- +
diff --git a/traque-front/components/admin/teamEdit.jsx b/traque-front/components/admin/teamEdit.jsx index 02e614c..0829c88 100644 --- a/traque-front/components/admin/teamEdit.jsx +++ b/traque-front/components/admin/teamEdit.jsx @@ -95,7 +95,7 @@ export default function TeamEdit({ selectedTeamId, setSelectedTeamId }) { updateTeam(team.id, { startingArea })} markerPosition={team?.currentLocation} />
- + {e.target.src = "/images/missing_image.jpg"}} />
diff --git a/traque-front/public/images/missing_image.jpg b/traque-front/public/images/missing_image.jpg new file mode 100644 index 0000000000000000000000000000000000000000..cba7e59ab21579d99261046e2ad8468faf78e080 GIT binary patch literal 10227 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