From eb7c323cfc15d64e25223ade97f5be3f8c4b1e6d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 Dec 2022 13:33:17 +0000 Subject: [PATCH 01/36] Bump express from 4.17.2 to 4.18.2 in /frontend Bumps [express](https://github.com/expressjs/express) from 4.17.2 to 4.18.2. - [Release notes](https://github.com/expressjs/express/releases) - [Changelog](https://github.com/expressjs/express/blob/master/History.md) - [Commits](https://github.com/expressjs/express/compare/4.17.2...4.18.2) --- updated-dependencies: - dependency-name: express dependency-type: indirect ... Signed-off-by: dependabot[bot] --- frontend/yarn.lock | 323 +++++++++++++++++++++++++++++---------------- 1 file changed, 207 insertions(+), 116 deletions(-) diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 9d5d575..1b3be7d 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -1563,12 +1563,13 @@ version "4.2.2" resolved "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz" -accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7: - version "1.3.7" - resolved "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz" +accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: + version "1.3.8" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== dependencies: - mime-types "~2.1.24" - negotiator "0.6.2" + mime-types "~2.1.34" + negotiator "0.6.3" acorn-jsx@^5.2.0: version "5.3.1" @@ -1708,7 +1709,8 @@ arr-union@^3.1.0: array-flatten@1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== array-flatten@^2.1.0: version "2.1.2" @@ -1989,20 +1991,23 @@ bn.js@^5.0.0, bn.js@^5.1.1: version "5.2.0" resolved "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz" -body-parser@1.19.1: - version "1.19.1" - resolved "https://registry.npmjs.org/body-parser/-/body-parser-1.19.1.tgz" +body-parser@1.20.1: + version "1.20.1" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668" + integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw== dependencies: - bytes "3.1.1" + bytes "3.1.2" content-type "~1.0.4" debug "2.6.9" - depd "~1.1.2" - http-errors "1.8.1" + depd "2.0.0" + destroy "1.2.0" + http-errors "2.0.0" iconv-lite "0.4.24" - on-finished "~2.3.0" - qs "6.9.6" - raw-body "2.4.2" + on-finished "2.4.1" + qs "6.11.0" + raw-body "2.5.1" type-is "~1.6.18" + unpipe "1.0.0" bonjour@^3.5.0: version "3.5.0" @@ -2160,9 +2165,10 @@ bytes@3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz" -bytes@3.1.1: - version "3.1.1" - resolved "https://registry.npmjs.org/bytes/-/bytes-3.1.1.tgz" +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== cacache@^12.0.2, cacache@^12.0.3: version "12.0.4" @@ -2211,7 +2217,8 @@ cache-loader@^4.1.0: call-bind@^1.0.0, call-bind@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== dependencies: function-bind "^1.1.1" get-intrinsic "^1.0.2" @@ -2593,13 +2600,15 @@ constants-browserify@^1.0.0: content-disposition@0.5.4: version "0.5.4" - resolved "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" + integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== dependencies: safe-buffer "5.2.1" content-type@~1.0.4: version "1.0.4" - resolved "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" + integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== convert-source-map@^1.7.0: version "1.8.0" @@ -2609,11 +2618,13 @@ convert-source-map@^1.7.0: cookie-signature@1.0.6: version "1.0.6" - resolved "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== -cookie@0.4.1: - version "0.4.1" - resolved "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz" +cookie@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" + integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== copy-concurrently@^1.0.0: version "1.0.5" @@ -3037,6 +3048,11 @@ delegate@^3.1.2: version "3.2.0" resolved "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz" +depd@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + depd@~1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz" @@ -3048,9 +3064,10 @@ des.js@^1.0.0: inherits "^2.0.1" minimalistic-assert "^1.0.0" -destroy@~1.0.4: - version "1.0.4" - resolved "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz" +destroy@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== detect-node@^2.0.4: version "2.1.0" @@ -3187,7 +3204,8 @@ ecc-jsbn@~0.1.1: ee-first@1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== ejs@^2.6.1: version "2.7.4" @@ -3233,7 +3251,8 @@ emojis-list@^3.0.0: encodeurl@~1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== end-of-stream@^1.0.0, end-of-stream@^1.1.0: version "1.4.4" @@ -3356,7 +3375,8 @@ escalade@^3.1.1: escape-html@~1.0.3: version "1.0.3" - resolved "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== escape-string-regexp@^1.0.5: version "1.0.5" @@ -3495,7 +3515,8 @@ esutils@^2.0.2: etag@~1.8.1: version "1.8.1" - resolved "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== event-pubsub@4.3.0: version "4.3.0" @@ -3505,15 +3526,15 @@ eventemitter3@^4.0.0: version "4.0.7" resolved "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz" -"events@^3.0.0": - "integrity" "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==" - "resolved" "https://registry.npmjs.org/events/-/events-3.3.0.tgz" - "version" "3.3.0" +events@^3.0.0: + version "3.3.0" + resolved "https://registry.npmjs.org/events/-/events-3.3.0.tgz" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== -"eventsource@^1.0.7": - "version" "1.1.1" - "resolved" "https://registry.yarnpkg.com/eventsource/-/eventsource-1.1.1.tgz#4544a35a57d7120fba4fa4c86cb4023b2c09df2f" - "integrity" sha512-qV5ZC0h7jYIAOhArFJgSfdyz6rALJyb270714o7ZtNnw2WSJ+eexhKtE0O8LYPRsHZHf2osHKZBxGPvm3kPkCA== +eventsource@^1.0.7: + version "1.1.1" + resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-1.1.1.tgz#4544a35a57d7120fba4fa4c86cb4023b2c09df2f" + integrity sha512-qV5ZC0h7jYIAOhArFJgSfdyz6rALJyb270714o7ZtNnw2WSJ+eexhKtE0O8LYPRsHZHf2osHKZBxGPvm3kPkCA== dependencies: original "^1.0.0" @@ -3576,36 +3597,38 @@ expand-brackets@^2.1.4: to-regex "^3.0.1" express@^4.16.3, express@^4.17.1: - version "4.17.2" - resolved "https://registry.npmjs.org/express/-/express-4.17.2.tgz" + version "4.18.2" + resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59" + integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ== dependencies: - accepts "~1.3.7" + accepts "~1.3.8" array-flatten "1.1.1" - body-parser "1.19.1" + body-parser "1.20.1" content-disposition "0.5.4" content-type "~1.0.4" - cookie "0.4.1" + cookie "0.5.0" cookie-signature "1.0.6" debug "2.6.9" - depd "~1.1.2" + depd "2.0.0" encodeurl "~1.0.2" escape-html "~1.0.3" etag "~1.8.1" - finalhandler "~1.1.2" + finalhandler "1.2.0" fresh "0.5.2" + http-errors "2.0.0" merge-descriptors "1.0.1" methods "~1.1.2" - on-finished "~2.3.0" + on-finished "2.4.1" parseurl "~1.3.3" path-to-regexp "0.1.7" proxy-addr "~2.0.7" - qs "6.9.6" + qs "6.11.0" range-parser "~1.2.1" safe-buffer "5.2.1" - send "0.17.2" - serve-static "1.14.2" + send "0.18.0" + serve-static "1.15.0" setprototypeof "1.2.0" - statuses "~1.5.0" + statuses "2.0.1" type-is "~1.6.18" utils-merge "1.0.1" vary "~1.1.2" @@ -3733,16 +3756,17 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" -finalhandler@~1.1.2: - version "1.1.2" - resolved "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz" +finalhandler@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" + integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== dependencies: debug "2.6.9" encodeurl "~1.0.2" escape-html "~1.0.3" - on-finished "~2.3.0" + on-finished "2.4.1" parseurl "~1.3.3" - statuses "~1.5.0" + statuses "2.0.1" unpipe "~1.0.0" find-cache-dir@^0.1.1: @@ -3831,7 +3855,8 @@ form-data@~2.3.2: forwarded@0.2.0: version "0.2.0" - resolved "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" + integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== fragment-cache@^0.2.1: version "0.2.1" @@ -3841,7 +3866,8 @@ fragment-cache@^0.2.1: fresh@0.5.2: version "0.5.2" - resolved "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== from2@^2.1.0: version "2.3.0" @@ -3901,7 +3927,8 @@ fsevents@~2.3.2: function-bind@^1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== functional-red-black-tree@^1.0.1: version "1.0.1" @@ -3915,7 +3942,16 @@ get-caller-file@^2.0.1, get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz" -get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: +get-intrinsic@^1.0.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.3.tgz#063c84329ad93e83893c7f4f243ef63ffa351385" + integrity sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.3" + +get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: version "1.1.1" resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz" dependencies: @@ -4090,6 +4126,11 @@ has-symbols@^1.0.1, has-symbols@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz" +has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + has-tostringtag@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz" @@ -4125,7 +4166,8 @@ has-values@^1.0.0: has@^1.0.0, has@^1.0.3: version "1.0.3" - resolved "https://registry.npmjs.org/has/-/has-1.0.3.tgz" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== dependencies: function-bind "^1.1.1" @@ -4246,14 +4288,15 @@ http-deceiver@^1.2.7: version "1.2.7" resolved "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz" -http-errors@1.8.1: - version "1.8.1" - resolved "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz" +http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== dependencies: - depd "~1.1.2" + depd "2.0.0" inherits "2.0.4" setprototypeof "1.2.0" - statuses ">= 1.5.0 < 2" + statuses "2.0.1" toidentifier "1.0.1" http-errors@~1.6.2: @@ -5178,7 +5221,8 @@ mdn-data@2.0.4: media-typer@0.3.0: version "0.3.0" - resolved "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== memory-fs@^0.4.1: version "0.4.1" @@ -5196,7 +5240,8 @@ memory-fs@^0.5.0: merge-descriptors@1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== merge-source-map@^1.1.0: version "1.1.0" @@ -5214,7 +5259,8 @@ merge2@^1.2.3: methods@~1.1.2: version "1.1.2" - resolved "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz" + resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== micromatch@^3.1.10, micromatch@^3.1.4: version "3.1.10" @@ -5252,15 +5298,28 @@ mime-db@1.51.0, "mime-db@>= 1.43.0 < 2": version "1.51.0" resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz" -mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24: +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.19: version "2.1.34" resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz" dependencies: mime-db "1.51.0" +mime-types@~2.1.24, mime-types@~2.1.34: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + mime@1.6.0: version "1.6.0" - resolved "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== mime@^2.4.4: version "2.6.0" @@ -5348,7 +5407,8 @@ move-concurrently@^1.0.1: ms@2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== ms@2.1.2, ms@^2.1.1: version "2.1.2" @@ -5356,7 +5416,8 @@ ms@2.1.2, ms@^2.1.1: ms@2.1.3: version "2.1.3" - resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== multicast-dns-service-types@^1.1.0: version "1.1.0" @@ -5405,9 +5466,10 @@ natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz" -negotiator@0.6.2: - version "0.6.2" - resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz" +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== neo-async@^2.5.0, neo-async@^2.6.0, neo-async@^2.6.1: version "2.6.2" @@ -5562,10 +5624,15 @@ object-hash@^1.1.4: version "1.3.1" resolved "https://registry.npmjs.org/object-hash/-/object-hash-1.3.1.tgz" -object-inspect@^1.11.0, object-inspect@^1.9.0: +object-inspect@^1.11.0: version "1.11.1" resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.1.tgz" +object-inspect@^1.9.0: + version "1.12.2" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" + integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== + object-is@^1.0.1: version "1.1.5" resolved "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz" @@ -5618,9 +5685,10 @@ obuf@^1.0.0, obuf@^1.1.2: version "1.1.2" resolved "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz" -on-finished@~2.3.0: - version "2.3.0" - resolved "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz" +on-finished@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== dependencies: ee-first "1.1.1" @@ -5836,7 +5904,8 @@ parseuri@0.0.6: parseurl@~1.3.2, parseurl@~1.3.3: version "1.3.3" - resolved "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== pascalcase@^0.1.1: version "0.1.1" @@ -5886,7 +5955,8 @@ path-parse@^1.0.6: path-to-regexp@0.1.7: version "0.1.7" - resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== path-type@^3.0.0: version "3.0.0" @@ -6323,7 +6393,8 @@ promise-inflight@^1.0.1: proxy-addr@~2.0.7: version "2.0.7" - resolved "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" + integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== dependencies: forwarded "0.2.0" ipaddr.js "1.9.1" @@ -6389,9 +6460,12 @@ q@^1.1.2: version "1.5.1" resolved "https://registry.npmjs.org/q/-/q-1.5.1.tgz" -qs@6.9.6: - version "6.9.6" - resolved "https://registry.npmjs.org/qs/-/qs-6.9.6.tgz" +qs@6.11.0: + version "6.11.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" + integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== + dependencies: + side-channel "^1.0.4" qs@~6.5.2: version "6.5.2" @@ -6432,14 +6506,16 @@ randomfill@^1.0.3: range-parser@^1.2.1, range-parser@~1.2.1: version "1.2.1" - resolved "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== -raw-body@2.4.2: - version "2.4.2" - resolved "https://registry.npmjs.org/raw-body/-/raw-body-2.4.2.tgz" +raw-body@2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" + integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== dependencies: - bytes "3.1.1" - http-errors "1.8.1" + bytes "3.1.2" + http-errors "2.0.0" iconv-lite "0.4.24" unpipe "1.0.0" @@ -6726,13 +6802,14 @@ rxjs@^6.6.0: dependencies: tslib "^1.9.0" -safe-buffer@5.1.2, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: +safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" -safe-buffer@5.2.1, safe-buffer@^5.2.0: +safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0: version "5.2.1" - resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== safe-regex@^1.1.0: version "1.1.0" @@ -6797,23 +6874,24 @@ semver@^7.3.4: dependencies: lru-cache "^6.0.0" -send@0.17.2: - version "0.17.2" - resolved "https://registry.npmjs.org/send/-/send-0.17.2.tgz" +send@0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" + integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== dependencies: debug "2.6.9" - depd "~1.1.2" - destroy "~1.0.4" + depd "2.0.0" + destroy "1.2.0" encodeurl "~1.0.2" escape-html "~1.0.3" etag "~1.8.1" fresh "0.5.2" - http-errors "1.8.1" + http-errors "2.0.0" mime "1.6.0" ms "2.1.3" - on-finished "~2.3.0" + on-finished "2.4.1" range-parser "~1.2.1" - statuses "~1.5.0" + statuses "2.0.1" serialize-javascript@^4.0.0: version "4.0.0" @@ -6833,14 +6911,15 @@ serve-index@^1.9.1: mime-types "~2.1.17" parseurl "~1.3.2" -serve-static@1.14.2: - version "1.14.2" - resolved "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz" +serve-static@1.15.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" + integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== dependencies: encodeurl "~1.0.2" escape-html "~1.0.3" parseurl "~1.3.3" - send "0.17.2" + send "0.18.0" set-blocking@^2.0.0: version "2.0.0" @@ -6865,7 +6944,8 @@ setprototypeof@1.1.0: setprototypeof@1.2.0: version "1.2.0" - resolved "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== sha.js@^2.4.0, sha.js@^2.4.8: version "2.4.11" @@ -6900,7 +6980,8 @@ shell-quote@^1.6.1: side-channel@^1.0.4: version "1.0.4" - resolved "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== dependencies: call-bind "^1.0.0" get-intrinsic "^1.0.2" @@ -7167,7 +7248,12 @@ static-extend@^0.1.1: define-property "^0.2.5" object-copy "^0.1.0" -"statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2", statuses@~1.5.0: +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + +"statuses@>= 1.4.0 < 2": version "1.5.0" resolved "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz" @@ -7516,7 +7602,8 @@ to-regex@^3.0.1, to-regex@^3.0.2: toidentifier@1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== toposort@^1.0.0: version "1.0.7" @@ -7590,7 +7677,8 @@ type-fest@^0.8.1: type-is@~1.6.18: version "1.6.18" - resolved "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== dependencies: media-typer "0.3.0" mime-types "~2.1.24" @@ -7679,7 +7767,8 @@ universalify@^2.0.0: unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== unquote@~1.1.1: version "1.1.1" @@ -7766,7 +7855,8 @@ utila@~0.4: utils-merge@1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== uuid@^3.3.2: version "3.4.0" @@ -7789,7 +7879,8 @@ validate-npm-package-license@^3.0.1: vary@~1.1.2: version "1.1.2" - resolved "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== vendors@^1.0.0: version "1.0.4" From 2c1d223cded12f8a4b1ff955e4013f29a9121897 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 Dec 2022 13:52:39 +0000 Subject: [PATCH 02/36] Bump minimatch from 3.0.4 to 3.1.2 in /frontend Bumps [minimatch](https://github.com/isaacs/minimatch) from 3.0.4 to 3.1.2. - [Release notes](https://github.com/isaacs/minimatch/releases) - [Changelog](https://github.com/isaacs/minimatch/blob/main/changelog.md) - [Commits](https://github.com/isaacs/minimatch/compare/v3.0.4...v3.1.2) --- updated-dependencies: - dependency-name: minimatch dependency-type: indirect ... Signed-off-by: dependabot[bot] --- frontend/yarn.lock | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 1b3be7d..06e05b3 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -1899,7 +1899,8 @@ backo2@1.0.2, backo2@~1.0.2: balanced-match@^1.0.0: version "1.0.2" - resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== base64-arraybuffer@0.1.4: version "0.1.4" @@ -2026,7 +2027,8 @@ boolbase@^1.0.0, boolbase@~1.0.0: brace-expansion@^1.1.7: version "1.1.11" - resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== dependencies: balanced-match "^1.0.0" concat-map "0.0.1" @@ -2569,7 +2571,8 @@ compression@^1.7.4: concat-map@0.0.1: version "0.0.1" - resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== concat-stream@^1.5.0: version "1.6.2" @@ -5351,8 +5354,9 @@ minimalistic-crypto-utils@^1.0.1: resolved "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz" minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz" + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== dependencies: brace-expansion "^1.1.7" From 0138c8b4fd4e1522f2cb580500585a68ed72bfff Mon Sep 17 00:00:00 2001 From: Alberto Xamin Date: Thu, 29 Dec 2022 15:43:52 +0000 Subject: [PATCH 03/36] speedup pull request tests --- .github/workflows/tests.yaml | 38 +++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 74a71c3..f902814 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -3,7 +3,7 @@ on: pull_request: jobs: - buildx: + build-amd64: runs-on: ubuntu-latest steps: - @@ -31,6 +31,24 @@ jobs: --output "type=image,push=false" \ --tag albertoxamin/bang:test \ --file ./Dockerfile ./ + build-arm64: + runs-on: ubuntu-latest + steps: + - + name: Checkout + uses: actions/checkout@v3 + - + name: Set up Docker Buildx + uses: crazy-max/ghaction-docker-buildx@v3 + - + name: Cache Docker layers + uses: actions/cache@v3 + id: cache + with: + path: /tmp/.buildx-cache + key: ${{ runner.os }}-buildx-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-buildx- - name: Docker Buildx (test build arm64) run: | @@ -41,6 +59,24 @@ jobs: --output "type=image,push=false" \ --tag albertoxamin/bang:test \ --file ./Dockerfile ./ + build-armv-7: + runs-on: ubuntu-latest + steps: + - + name: Checkout + uses: actions/checkout@v3 + - + name: Set up Docker Buildx + uses: crazy-max/ghaction-docker-buildx@v3 + - + name: Cache Docker layers + uses: actions/cache@v3 + id: cache + with: + path: /tmp/.buildx-cache + key: ${{ runner.os }}-buildx-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-buildx- - name: Docker Buildx (test build armv-7) run: | From 7e2c218c3d193775b67160aefc8616ff2d5f9cc0 Mon Sep 17 00:00:00 2001 From: Alberto Xamin Date: Thu, 29 Dec 2022 16:36:45 +0000 Subject: [PATCH 04/36] notify scrap pile on reconnection --- backend/server.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/backend/server.py b/backend/server.py index d108a22..191746a 100644 --- a/backend/server.py +++ b/backend/server.py @@ -124,6 +124,7 @@ def get_me(sid, room): de_games[0].notify_room(sid) eventlet.sleep(0.1) de_games[0].notify_all() + de_games[0].notify_scrap_pile(sid) sio.emit('role', room=sid, data=json.dumps(bot.role, default=lambda o: o.__dict__)) bot.notify_self() if len(bot.available_characters) > 0: @@ -133,6 +134,8 @@ def get_me(sid, room): sio.get_session(sid).game = de_games[0] sio.enter_room(sid, de_games[0].name) de_games[0].notify_room(sid) + eventlet.sleep(0.1) + de_games[0].notify_event_card(sid) de_games[0].notify_scrap_pile(sid) de_games[0].notify_all() From 30f1251b3c024869a8e488f271f1ee6b8a862430 Mon Sep 17 00:00:00 2001 From: Alberto Xamin Date: Fri, 30 Dec 2022 16:45:21 +0000 Subject: [PATCH 05/36] fix manette --- backend/bang/players.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/bang/players.py b/backend/bang/players.py index 8daf297..336cf68 100644 --- a/backend/bang/players.py +++ b/backend/bang/players.py @@ -627,9 +627,9 @@ class Player: withCard = self.hand.pop(_with) if hand_index > _with else self.hand.pop(_with - 1) print(self.name, 'is playing ', card, ' against:', against, ' with:', _with) did_play_card = False - event_blocks_card = (self.game.check_event(ce.IlGiudice) and (card.is_equipment or (card.usable_next_turn and not card.can_be_used_now))) or (self.game.check_event(ce.Lazo) and card.usable_next_turn and card.can_be_used_now) or (self.game.check_event(ceh.Manette) and card.suit != self.committed_suit_manette and not (card.usable_next_turn and card.can_be_used_now)) + event_blocks_card = (self.game.check_event(ce.IlGiudice) and (card.is_equipment or (card.usable_next_turn and not card.can_be_used_now))) or (self.game.check_event(ce.Lazo) and card.usable_next_turn and card.can_be_used_now) or ((self.game.check_event(ceh.Manette) and card.suit != self.committed_suit_manette) and not (card.usable_next_turn and card.can_be_used_now)) if not(against != None and (self.game.get_player_named(against).character.check(self.game, chd.ApacheKid) or len([c for c in self.game.get_player_named(against).gold_rush_equipment if isinstance(c, grc.Calumet)]) > 0) and card.check_suit(self.game, [cs.Suit.DIAMONDS])) or (isinstance(card, grc.ShopCard) and card.kind == grc.ShopCardKind.BLACK) and not event_blocks_card: - if against == self.name and not isinstance(card, csd.Tequila) and not isinstance(card, cs.Panico) and not isinstance(card, cs.CatBalou): + if (against == self.name and not isinstance(card, csd.Tequila) and not isinstance(card, cs.Panico) and not isinstance(card, cs.CatBalou)) or event_blocks_card: did_play_card = False else: did_play_card = card.play_card(self, against, withCard) From e97c0d4bda194bd15e14ac05d5101762ecc159af Mon Sep 17 00:00:00 2001 From: Alberto Xamin Date: Mon, 2 Jan 2023 12:42:23 +0000 Subject: [PATCH 06/36] fix broken report --- backend/server.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/backend/server.py b/backend/server.py index 191746a..b1e14d6 100644 --- a/backend/server.py +++ b/backend/server.py @@ -66,22 +66,23 @@ def get_online_players(sid): @sio.event def report(sid, text): + print(f'New report from {sid}: {text}') ses: Player = sio.get_session(sid) data='' if hasattr(ses, 'game'): data = "\n".join(ses.game.rpc_log[:-1]).strip() data = data +"\n@@@\n" +text #print(data) - response = requests.post("https://www.toptal.com/developers/hastebin/documents", data) + response = requests.post("https://hastebin.com/documents", data) key = json.loads(response.text).get('key') if "DISCORD_WEBHOOK" in os.environ and len(os.environ['DISCORD_WEBHOOK']) > 0: - webhook = DiscordWebhook(url=os.environ['DISCORD_WEBHOOK'], content=f'New bug report, replay at https://www.toptal.com/developers/hastebin/{key}') + webhook = DiscordWebhook(url=os.environ['DISCORD_WEBHOOK'], content=f'New bug report, replay at https://hastebin.com/documents/{key}') response = webhook.execute() sio.emit('chat_message', room=sid, data={'color': f'green','text':f'Report OK'}) else: print("WARNING: DISCORD_WEBHOOK not found") Metrics.send_event('BUG_REPORT', event_data=text) - print(f'New bug report, replay at https://www.toptal.com/developers/hastebin/{key}') + print(f'New bug report, replay at https://hastebin.com/documents/{key}') @sio.event def set_username(sid, username): @@ -373,7 +374,7 @@ def chat_message(sid, msg, pl=None): _cmd = msg.split() if len(_cmd) >= 2: replay_id = _cmd[1] - response = requests.get(f"https://www.toptal.com/developers/hastebin/raw/{replay_id}") + response = requests.get(f"https://hastebin.com/documents/{replay_id}") log = response.text.splitlines() ses.game.spectators.append(ses) if len(_cmd) == 2: From 4d48a4bd694d074e3f9d98108aada59ab990b93d Mon Sep 17 00:00:00 2001 From: Alberto Xamin Date: Tue, 3 Jan 2023 13:50:41 +0000 Subject: [PATCH 07/36] add discord login --- backend/bang/game.py | 4 ++- backend/bang/players.py | 39 +++++++++++++++++++++++++++++- backend/server.py | 21 ++++++++++++++-- frontend/src/components/Card.vue | 26 ++++++++++++++++++-- frontend/src/components/Lobby.vue | 6 +++-- frontend/src/components/Menu.vue | 38 +++++++++++++++++++++++++++-- frontend/src/components/Player.vue | 2 ++ 7 files changed, 126 insertions(+), 10 deletions(-) diff --git a/backend/bang/game.py b/backend/bang/game.py index 3548454..828ecf3 100644 --- a/backend/bang/game.py +++ b/backend/bang/game.py @@ -149,7 +149,7 @@ class Game: self.sio.emit('room', room=self.name if not sid else sid, data={ 'name': self.name, 'started': self.started, - 'players': [{'name':p.name, 'ready': p.character != None, 'is_bot': p.is_bot} for p in self.players], + 'players': [{'name':p.name, 'ready': p.character != None, 'is_bot': p.is_bot, 'avatar': p.avatar} for p in self.players], 'password': self.password, 'is_competitive': self.is_competitive, 'disconnect_bot': self.disconnect_bot, @@ -763,6 +763,7 @@ class Game: 'is_ghost': pls[j].is_ghost, 'is_bot': pls[j].is_bot, 'icon': pls[j].role.icon if (pls[j].role is not None) else '🤠', + 'avatar': pls[j].avatar, 'role': pls[j].role, } for j in range(len(pls)) if i != j] @@ -788,6 +789,7 @@ class Game: 'character': p.character.__dict__ if p.character else None, 'real_character': p.real_character.__dict__ if p.real_character else None, 'icon': p.role.icon if self.initial_players == 3 and p.role else '🤠', + 'avatar': p.avatar, 'is_ghost': p.is_ghost, 'is_bot': p.is_bot, } for p in self.get_alive_players()] diff --git a/backend/bang/players.py b/backend/bang/players.py index 336cf68..67cd0f8 100644 --- a/backend/bang/players.py +++ b/backend/bang/players.py @@ -16,6 +16,18 @@ import eventlet from typing import List from metrics import Metrics +robot_pictures = [ + 'https://i.imgur.com/40rAFIb.jpg', + 'https://i.imgur.com/gG77VRR.jpg', + 'https://i.imgur.com/l2DTQeH.jpg', + 'https://i.imgur.com/aPM2gix.jpg', + 'https://i.imgur.com/ep5EB8c.jpg', + 'https://i.imgur.com/qsOWIsf.jpg', + 'https://emojipedia-us.s3.dualstack.us-west-1.amazonaws.com/thumbs/240/apple/325/robot_1f916.png', + 'https://emojipedia-us.s3.dualstack.us-west-1.amazonaws.com/thumbs/240/openmoji/338/robot_1f916.png', + 'https://emojipedia-us.s3.dualstack.us-west-1.amazonaws.com/thumbs/240/microsoft/319/robot_1f916.png', +] + class PendingAction(IntEnum): PICK = 0 DRAW = 1 @@ -26,13 +38,37 @@ class PendingAction(IntEnum): class Player: - def __init__(self, name, sid, sio, bot=False): + def get_avatar(self): + import requests + headers = { + 'Authorization': 'Bearer ' + self.discord_token, + } + r = requests.get('https://discordapp.com/api/users/@me', headers=headers) + if r.status_code == 200: + res = r.json() + self.avatar = f'https://cdn.discordapp.com/avatars/{res["id"]}/{res["avatar"]}.png' + self.sio.emit('chat_message', room=self.game.name, data=f'_change_username|{self.name}|{res["username"]}') + self.name = res['username'] + if self.game: + self.game.notify_room() + self.sio.emit('me', data=self.name, room=self.sid) + else: + print('error getting avatar', r.status_code, r.text) + print(r) + + def __init__(self, name, sid, sio, bot=False, discord_token=None): import bang.game as g super().__init__() self.name = name self.sid = sid self.sio = sio self.is_bot = bot + self.discord_token = discord_token + self.avatar = '' + if self.is_bot: + self.avatar = robot_pictures[randrange(len(robot_pictures))] + if self.discord_token: + sio.start_background_task(self.get_avatar) self.game: g = None self.reset() @@ -207,6 +243,7 @@ class Player: ser.pop('sio') ser.pop('sid') ser.pop('on_pick_cb') + ser.pop('discord_token') ser.pop('on_failed_response_cb') ser.pop('attacker') ser.pop('rissa_targets') diff --git a/backend/server.py b/backend/server.py index b1e14d6..5fa497c 100644 --- a/backend/server.py +++ b/backend/server.py @@ -88,10 +88,11 @@ def report(sid, text): def set_username(sid, username): ses = sio.get_session(sid) if not isinstance(ses, Player): - sio.save_session(sid, Player(username, sid, sio)) + sio.save_session(sid, Player(username["name"], sid, sio, discord_token=username["discord_token"])) print(f'{sid} is now {username}') advertise_lobbies() elif ses.game == None or not ses.game.started: + username = username["name"] print(f'{sid} changed username to {username}') prev = ses.name if len([p for p in ses.game.players if p.name == username]) > 0: @@ -109,7 +110,7 @@ def get_me(sid, room): if sio.get_session(sid).game: sio.get_session(sid).game.notify_room() else: - sio.save_session(sid, Player('player', sid, sio)) + sio.save_session(sid, Player('player', sid, sio, discord_token=room['discord_token'])) de_games = [g for g in games if g.name == room['name']] if len(de_games) == 1 and not de_games[0].started: join_room(sid, room) @@ -612,6 +613,18 @@ def get_goldrushcards(sid): cards = [cards_dict[i] for i in cards_dict] sio.emit('goldrushcards_info', room=sid, data=json.dumps(cards, default=lambda o: o.__dict__)) +@sio.event +def discord_auth(sid, data): + res = requests.post('https://discord.com/api/oauth2/token', data={ + 'client_id': '1059452581027532880', + 'client_secret': 'Mc8ZlMQhayzi1eOqWFtGHs3L0iXCzaEu', + 'grant_type': 'authorization_code', + 'redirect_uri': data['origin'], + 'code': data['code'], + }) + if res.status_code == 200: + sio.emit('discord_auth_succ', room=sid, data=res.json()) + def pool_metrics(): sio.sleep(60) Metrics.send_metric('lobbies', points=[len([g for g in games if not g.is_replay])]) @@ -636,6 +649,10 @@ class CustomProxyFix(object): return [''] return self.app(environ, start_response) + +discord_ci = '1059452581027532880' +discord_cs = 'Mc8ZlMQhayzi1eOqWFtGHs3L0iXCzaEu' + if __name__ == '__main__': sio.start_background_task(pool_metrics) eventlet.wsgi.server(eventlet.listen(('', 5001)), CustomProxyFix(app)) diff --git a/frontend/src/components/Card.vue b/frontend/src/components/Card.vue index d1dd002..f1ef573 100644 --- a/frontend/src/components/Card.vue +++ b/frontend/src/components/Card.vue @@ -1,7 +1,8 @@ @@ -98,6 +104,7 @@ import Player from './Player.vue' import Deck from './Deck.vue' import TinyHand from './TinyHand.vue' import FullScreenInput from './FullScreenInput.vue' +import Status from './Status.vue' export default { name: 'Lobby', @@ -109,7 +116,8 @@ export default { Deck, TinyHand, PrettyCheck, - FullScreenInput + FullScreenInput, + Status }, data: () => ({ username: '', @@ -134,6 +142,7 @@ export default { debug_mode: false, showTurnFlow: false, turnReversed: false, + displayAdminStatus: false, turn: -1, }), sockets: { @@ -180,6 +189,9 @@ export default { this.username = username // this.$socket.emit('get_cards', 'dodge_city') }, + mount_status() { + this.displayAdminStatus = true + }, // cards_info(data) { // data = JSON.parse(data) // let bigthing = {} diff --git a/frontend/src/components/Status.vue b/frontend/src/components/Status.vue index 58fc9c5..48f1fb7 100644 --- a/frontend/src/components/Status.vue +++ b/frontend/src/components/Status.vue @@ -31,9 +31,15 @@ From f6e8d193af194bc65ad144ab3320208c9ab267af Mon Sep 17 00:00:00 2001 From: Alberto Xamin Date: Mon, 8 Feb 2021 12:12:31 +0100 Subject: [PATCH 11/36] add cards of valley of shadows --- backend/bang/cards.py | 4 +- backend/bang/characters.py | 4 +- backend/bang/expansions/__init__.py | 9 ++ .../expansions/the_valley_of_shadows/cards.py | 114 ++++++++++++++++++ .../the_valley_of_shadows/characters.py | 10 ++ backend/bang/game.py | 2 +- 6 files changed, 140 insertions(+), 3 deletions(-) create mode 100644 backend/bang/expansions/the_valley_of_shadows/cards.py create mode 100644 backend/bang/expansions/the_valley_of_shadows/characters.py diff --git a/backend/bang/cards.py b/backend/bang/cards.py index 17970d9..e8a09ab 100644 --- a/backend/bang/cards.py +++ b/backend/bang/cards.py @@ -445,7 +445,7 @@ class WellsFargo(Card): def get_starting_deck(expansions:List[str]) -> List[Card]: - from bang.expansions import DodgeCity + from bang.expansions import DodgeCity, TheValleyOfShadows base_cards = [ Barile(Suit.SPADES, 'Q'), Barile(Suit.SPADES, 'K'), @@ -530,5 +530,7 @@ def get_starting_deck(expansions:List[str]) -> List[Card]: ] if 'dodge_city' in expansions: base_cards.extend(DodgeCity.get_cards()) + if 'the_valley_of_shadows' in expansions: + base_cards.extend(TheValleyOfShadows.get_cards()) return base_cards diff --git a/backend/bang/characters.py b/backend/bang/characters.py index 47c66c4..e327a28 100644 --- a/backend/bang/characters.py +++ b/backend/bang/characters.py @@ -145,7 +145,7 @@ class WillyTheKid(Character): self.icon = '🎉' def all_characters(expansions: List[str]): - from bang.expansions import DodgeCity + from bang.expansions import DodgeCity, TheValleyOfShadows base_chars = [ BartCassidy(), BlackJack(), @@ -168,4 +168,6 @@ def all_characters(expansions: List[str]): base_chars.extend(DodgeCity.get_characters()) if 'gold_rush' in expansions: base_chars.extend(GoldRush.get_characters()) + if 'the_valley_of_shadows' in expansions: + base_chars.extend(TheValleyOfShadows.get_characters()) return base_chars \ No newline at end of file diff --git a/backend/bang/expansions/__init__.py b/backend/bang/expansions/__init__.py index 616b8c7..ebae2dd 100644 --- a/backend/bang/expansions/__init__.py +++ b/backend/bang/expansions/__init__.py @@ -13,3 +13,12 @@ class GoldRush(): def get_characters(): from bang.expansions.gold_rush import characters return characters.all_characters() + +class TheValleyOfShadows(): + def get_characters(): + from bang.expansions.the_valley_of_shadows import characters + return characters.all_characters() + + def get_cards(): + from bang.expansions.the_valley_of_shadows import cards + return cards.get_starting_deck() diff --git a/backend/bang/expansions/the_valley_of_shadows/cards.py b/backend/bang/expansions/the_valley_of_shadows/cards.py new file mode 100644 index 0000000..340f509 --- /dev/null +++ b/backend/bang/expansions/the_valley_of_shadows/cards.py @@ -0,0 +1,114 @@ +from bang.cards import * + +class Fantasma(Card): + def __init__(self, suit, number): + super().__init__(suit, 'Fantasma', number, is_equipment=True) + self.icon = '👻️' #porta in vita i giocatori morti ma non + #TODO + +class Lemat(Card): + def __init__(self, suit, number): + super().__init__(suit, 'Lemat', number, is_equipment=True, is_weapon=True, range=1) + self.icon = '🔫' # ogni carta può essere usata come bang + #TODO + +class SerpenteASonagli(Card): + def __init__(self, suit, number): + super().__init__(suit, 'SerpenteASonagli', number, is_equipment=True) + self.need_target = True + self.icon = '🐍️' # Ogni turno pesca se il seme picche -1hp + #TODO + +class Shotgun(Card): + def __init__(self, suit, number): + super().__init__(suit, 'Shotgun', number, is_equipment=True, range=1) + self.icon = '🔫' # Ogni volta che colpisci un giocatore deve scartare una carta + #TODO + +class Taglia(Card): + def __init__(self, suit, number): + super().__init__(suit, 'Taglia', number, is_equipment=True) + self.need_target = True + self.icon = '💰' # chiunque colpisca il giocatore con la taglia pesca una carta dal mazzo, si toglie solo con panico, cat balou, dalton + #TODO + +class UltimoGiro(Card): + def __init__(self, suit, number): + super().__init__(suit, 'Ultimo Giro', number) + self.icon = '🥂' + # self.desc = 'Recupera 1 vita' + # self.desc_eng = 'Regain 1 HP' + self.alt_text = "🍺" + + def play_card(self, player, against, _with=None): + super().play_card(player, against) + player.lives = min(player.lives+1, player.max_lives) + player.notify_self() + return True + +class Tomahawk(Card): + def __init__(self, suit, number): + super().__init__(suit, 'Tomahawk', number, range=2) + self.icon = '🪓️' + self.alt_text = "2🔎 💥" + # "Spara a un giocatore a distanza 2" + self.need_target = True + + def play_card(self, player, against, _with=None): + if against != None: + super().play_card(player, against=against) + player.game.attack(player, against) + return True + return False + +class Sventagliata(Card): + def __init__(self, suit, number): + super().__init__(suit, 'Sventagliata', number) + self.icon = '💕️' + self.alt_text = "💥💥" # spara al target e anche, a uno a distanza 1 dal target + self.need_target = True + + def play_card(self, player, against, _with=None): + if against != None: + #TODO + # super().play_card(player, against=against) + # player.game.attack(player, against) + return True + return False + +class Salvo(Card): + def __init__(self, suit, number): + super().__init__(suit, 'Salvo!', number) + self.icon = '😇️' + self.alt_text = "👤😇️" # spara al target e anche, a uno a distanza 1 dal target + self.need_target = True + + def play_card(self, player, against, _with=None): + if against != None: + #TODO + # super().play_card(player, against=against) + # player.game.attack(player, against) + return True + return False + +def get_starting_deck() -> List[Card]: + cards = [ + Fantasma(Suit.SPADES, 9), + Fantasma(Suit.SPADES, 10), + Lemat(Suit.DIAMONDS, 4), + SerpenteASonagli(Suit.HEARTS, 7), + Shotgun(Suit.SPADES, 'K'), + Taglia(Suit.CLUBS, 9), + UltimoGiro(Suit.DIAMONDS, 8), + Tomahawk(Suit.DIAMONDS, 'A'), + Sventagliata(Suit.SPADES, 2), + Salvo(Suit.HEARTS, 5), + # Bandidos(Suit.DIAMONDS,'Q'), # gli altri giocatori scelgono se scartare 2 carte o perdere 1 punto vita + # Fuga(Suit.HEARTS, 3), # evita l'effetto di carte marroni (tipo panico cat balou) di cui sei bersaglio + # Mira(Suit.CLUBS, 6), # gioca questa con una carta bang, per fare -2hp + # Poker(Suit.HEARTS, 'J'), # tutti gli altri scartano 1 carta a scelta, se non ci sono assi allora pesca 2 dal mazzo + # RitornoDiFiamma(Suit.CLUBS, 'Q'), # un mancato che fa bang + ] + for c in cards: + c.expansion_icon = '👻️' + return cards diff --git a/backend/bang/expansions/the_valley_of_shadows/characters.py b/backend/bang/expansions/the_valley_of_shadows/characters.py new file mode 100644 index 0000000..feebfd1 --- /dev/null +++ b/backend/bang/expansions/the_valley_of_shadows/characters.py @@ -0,0 +1,10 @@ +from typing import List +from bang.characters import * + +def all_characters() -> List[Character]: + cards = [ + + ] + for c in cards: + c.expansion_icon = '👻️' + return cards diff --git a/backend/bang/game.py b/backend/bang/game.py index bb0bc09..32b99a4 100644 --- a/backend/bang/game.py +++ b/backend/bang/game.py @@ -30,7 +30,7 @@ class Game: self.initial_players = 0 self.password = '' self.expansions: List[str] = [] - self.available_expansions = ['dodge_city', 'fistful_of_cards', 'high_noon', 'gold_rush'] + self.available_expansions = ['dodge_city', 'fistful_of_cards', 'high_noon', 'gold_rush', 'the_valley_of_shadows'] self.shutting_down = False self.is_competitive = False self.disconnect_bot = True From 916d9af322c6c9b380cc69ee68c6c8f62b2754ba Mon Sep 17 00:00:00 2001 From: Alberto Xamin Date: Wed, 4 Jan 2023 14:09:17 +0000 Subject: [PATCH 12/36] add valley of shadows under feature flag --- .../expansions/the_valley_of_shadows/cards.py | 7 +- backend/bang/game.py | 8 ++- backend/bang/players.py | 1 + backend/server.py | 22 ++++++ frontend/src/components/Help.vue | 16 +++++ frontend/src/i18n/en.json | 69 +++++++++++++++++-- frontend/src/i18n/it.json | 63 ++++++++++++++++- 7 files changed, 177 insertions(+), 9 deletions(-) diff --git a/backend/bang/expansions/the_valley_of_shadows/cards.py b/backend/bang/expansions/the_valley_of_shadows/cards.py index 340f509..096ddb4 100644 --- a/backend/bang/expansions/the_valley_of_shadows/cards.py +++ b/backend/bang/expansions/the_valley_of_shadows/cards.py @@ -17,6 +17,7 @@ class SerpenteASonagli(Card): super().__init__(suit, 'SerpenteASonagli', number, is_equipment=True) self.need_target = True self.icon = '🐍️' # Ogni turno pesca se il seme picche -1hp + self.alt_text = "♠️=💔" #TODO class Shotgun(Card): @@ -34,7 +35,7 @@ class Taglia(Card): class UltimoGiro(Card): def __init__(self, suit, number): - super().__init__(suit, 'Ultimo Giro', number) + super().__init__(suit, 'UltimoGiro', number) self.icon = '🥂' # self.desc = 'Recupera 1 vita' # self.desc_eng = 'Regain 1 HP' @@ -78,9 +79,9 @@ class Sventagliata(Card): class Salvo(Card): def __init__(self, suit, number): - super().__init__(suit, 'Salvo!', number) + super().__init__(suit, 'Salvo', number) self.icon = '😇️' - self.alt_text = "👤😇️" # spara al target e anche, a uno a distanza 1 dal target + self.alt_text = "👤😇️" self.need_target = True def play_card(self, player, against, _with=None): diff --git a/backend/bang/game.py b/backend/bang/game.py index 32b99a4..1679b32 100644 --- a/backend/bang/game.py +++ b/backend/bang/game.py @@ -30,7 +30,7 @@ class Game: self.initial_players = 0 self.password = '' self.expansions: List[str] = [] - self.available_expansions = ['dodge_city', 'fistful_of_cards', 'high_noon', 'gold_rush', 'the_valley_of_shadows'] + self.available_expansions = ['dodge_city', 'fistful_of_cards', 'high_noon', 'gold_rush'] self.shutting_down = False self.is_competitive = False self.disconnect_bot = True @@ -204,6 +204,10 @@ class Game: self.disconnect_bot = not self.disconnect_bot self.notify_room() + def feature_flags(self): + self.available_expansions.append('the_valley_of_shadows') + self.notify_room() + def add_player(self, player: pl.Player): if player.is_bot and len(self.players) >= 8: return @@ -213,6 +217,8 @@ class Game: if 'dodge_city' not in self.expansions: self.expansions.append('dodge_city') player.join_game(self) + if player.is_admin(): + self.feature_flags() self.players.append(player) print(f'{self.name}: Added player {player.name} to game') self.notify_room() diff --git a/backend/bang/players.py b/backend/bang/players.py index 042c828..2f2defa 100644 --- a/backend/bang/players.py +++ b/backend/bang/players.py @@ -55,6 +55,7 @@ class Player: self.name = res['username'] self.discord_id = res['id'] if self.is_admin(): + if self.game: self.game.feature_flags() self.sio.emit('chat_message', room=self.sid, data={'color':'green', 'text':'(you are admin)'}) if self.game: self.game.notify_room() diff --git a/backend/server.py b/backend/server.py index 94c7d10..8ced009 100644 --- a/backend/server.py +++ b/backend/server.py @@ -546,6 +546,17 @@ def chat_message(sid, msg, pl=None): for cn in card_names: ses.hand.append([c for c in cards if c.name.lower() == cn.lower() or c.name[0:-1].lower() == cn.lower()][0]) ses.notify_self() + elif '/getset' in msg: + sio.emit('chat_message', room=ses.game.name, data={'color': f'red','text':f'🚨 {ses.name} is in debug mode and got a card'}) + cmd = msg.split() + if len(cmd) >= 2: + from bang.expansions import DodgeCity, TheValleyOfShadows + if cmd[1] == 'dodgecity': + ses.hand = DodgeCity.get_cards() + ses.notify_self() + elif 'valley' in cmd[1].lower(): + ses.hand = TheValleyOfShadows.get_cards() + ses.notify_self() elif '/getnuggets' in msg: sio.emit('chat_message', room=ses.game.name, data={'color': f'red','text':f'🚨 {ses.name} is in debug mode and got nuggets'}) import bang.cards as cs @@ -634,6 +645,17 @@ def get_goldrushcards(sid): cards = [cards_dict[i] for i in cards_dict] sio.emit('goldrushcards_info', room=sid, data=json.dumps(cards, default=lambda o: o.__dict__)) +@sio.event +def get_valleyofshadowscards(sid): + import bang.expansions.the_valley_of_shadows.cards as tvos + cards = tvos.get_starting_deck() + cards_dict = {} + for ca in cards: + if ca.name not in cards_dict: + cards_dict[ca.name] = ca + cards = [cards_dict[i] for i in cards_dict] + sio.emit('valleyofshadows_info', room=sid, data=json.dumps(cards, default=lambda o: o.__dict__)) + @sio.event def discord_auth(sid, data): res = requests.post('https://discord.com/api/oauth2/token', data={ diff --git a/frontend/src/components/Help.vue b/frontend/src/components/Help.vue index a7159dc..9fc6e49 100644 --- a/frontend/src/components/Help.vue +++ b/frontend/src/components/Help.vue @@ -108,6 +108,15 @@ +

{{$t('help.valleyofshadowscards')}}

+
+
+ +
+

{{$t(`cards.${c.name}.desc`)}}

+
+
+
diff --git a/frontend/src/components/Menu.vue b/frontend/src/components/Menu.vue index 7fa622d..0285674 100644 --- a/frontend/src/components/Menu.vue +++ b/frontend/src/components/Menu.vue @@ -169,6 +169,7 @@ export default { this.username = data.username this.didSetUsername = true this.discordPic = `https://cdn.discordapp.com/avatars/${data.id}/${data.avatar}.png` + localStorage.setItem('username', this.username) this.$socket.emit('set_username', {name: this.username, discord_token: localStorage.getItem('discord_token')}) }).catch(err => { console.error(err) diff --git a/frontend/src/components/Player.vue b/frontend/src/components/Player.vue index 00aa91d..a986c20 100644 --- a/frontend/src/components/Player.vue +++ b/frontend/src/components/Player.vue @@ -49,15 +49,15 @@ - - + + - + From 8ffae000ef7afd5dbf774a3c570a21297cf00ffd Mon Sep 17 00:00:00 2001 From: Alberto Xamin Date: Sat, 7 Jan 2023 09:43:07 +0000 Subject: [PATCH 18/36] add hand count --- frontend/src/components/Player.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/components/Player.vue b/frontend/src/components/Player.vue index a986c20..c673afd 100644 --- a/frontend/src/components/Player.vue +++ b/frontend/src/components/Player.vue @@ -37,6 +37,7 @@
{{$t('hand')}} + {{hand.length}}/{{maxHandLength()}} Date: Sat, 7 Jan 2023 09:43:54 +0000 Subject: [PATCH 19/36] fix broken bot spin --- backend/bang/players.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/bang/players.py b/backend/bang/players.py index 1c54347..22e6a8a 100644 --- a/backend/bang/players.py +++ b/backend/bang/players.py @@ -609,7 +609,7 @@ class Player: self.game.next_player().equipment.append(self.equipment.pop(i)) self.game.next_player().notify_self() break - if any((isinstance(c, cs.Dinamite) or isinstance(c, cs.Prigione) or isinstance(self.equipment[i], tvosc.SerpenteASonagli) for c in self.equipment)): + if any((isinstance(c, cs.Dinamite) or isinstance(c, cs.Prigione) or isinstance(c, tvosc.SerpenteASonagli) for c in self.equipment)): self.notify_self() return for i in range(len(self.equipment)): From ed057502d6198ef5b23df4758216c84890a44083 Mon Sep 17 00:00:00 2001 From: Alberto Xamin Date: Sat, 7 Jan 2023 11:15:40 +0000 Subject: [PATCH 20/36] add ritorno di fiamma --- .../expansions/the_valley_of_shadows/cards.py | 17 ++--- backend/bang/players.py | 12 +++- backend/tests/character_test.py | 2 - backend/tests/valley_of_shadows_test.py | 71 +++++++++++++++++++ 4 files changed, 90 insertions(+), 12 deletions(-) diff --git a/backend/bang/expansions/the_valley_of_shadows/cards.py b/backend/bang/expansions/the_valley_of_shadows/cards.py index ed8f828..8c90d0b 100644 --- a/backend/bang/expansions/the_valley_of_shadows/cards.py +++ b/backend/bang/expansions/the_valley_of_shadows/cards.py @@ -1,7 +1,7 @@ from typing import List import bang.roles as r import bang.players as pl -from bang.cards import Card, Suit, Bang +from bang.cards import Card, Suit, Bang, Mancato import bang.expansions.fistful_of_cards.card_events as ce class Fantasma(Card): @@ -177,17 +177,18 @@ class Poker(Card): # player.game.attack(player, against) return True -class RitornoDiFiamma(Card): +class RitornoDiFiamma(Mancato): def __init__(self, suit, number): - super().__init__(suit, 'RitornoDiFiamma', number) + super().__init__(suit, number) + self.name = 'RitornoDiFiamma' self.icon = '🔥' self.alt_text = "😅 | 💥" def play_card(self, player, against, _with=None): - #TODO - # super().play_card(player, against=against) - # player.game.attack(player, against) - return True + return False + + def use_card(self, player): + player.notify_self() def get_starting_deck() -> List[Card]: cards = [ @@ -205,7 +206,7 @@ def get_starting_deck() -> List[Card]: # Fuga(Suit.HEARTS, 3), # evita l'effetto di carte marroni (tipo panico cat balou) di cui sei bersaglio # Mira(Suit.CLUBS, 6), # Poker(Suit.HEARTS, 'J'), # tutti gli altri scartano 1 carta a scelta, se non ci sono assi allora pesca 2 dal mazzo - # RitornoDiFiamma(Suit.CLUBS, 'Q'), # un mancato che fa bang + RitornoDiFiamma(Suit.CLUBS, 'Q'), # un mancato che fa bang ] for c in cards: c.expansion_icon = '👻️' diff --git a/backend/bang/players.py b/backend/bang/players.py index 22e6a8a..269e3b5 100644 --- a/backend/bang/players.py +++ b/backend/bang/players.py @@ -426,13 +426,13 @@ class Player: data=f'_turn|{self.name}') print(f'{self.name}: I was notified that it is my turn') self.was_shot = False + self.attacker = None self.is_my_turn = True self.is_waiting_for_action = True self.has_played_bang = False self.special_use_count = 0 self.bang_used = 0 if self.game.check_event(ceh.MezzogiornoDiFuoco): - self.attacker = None self.lives -= 1 if len([c for c in self.gold_rush_equipment if isinstance(c, grc.Talismano)]) > 0: self.gold_nuggets += 1 @@ -576,7 +576,7 @@ class Player: pickable_cards = 1 + self.character.pick_mod if len([c for c in self.gold_rush_equipment if isinstance(c, grc.FerroDiCavallo)]) > 0: pickable_cards += 1 - if self.is_my_turn: + if self.is_my_turn and self.attacker == None: for i in range(len(self.equipment)): if i < len(self.equipment) and isinstance(self.equipment[i], cs.Dinamite): while pickable_cards > 0: @@ -1212,7 +1212,15 @@ class Player: self.molly_discarded_cards = 0 self.notify_self() self.game.responders_did_respond_resume_turn(did_lose=False) + if isinstance(card, tvosc.RitornoDiFiamma): + self.game.attack(self, self.attacker.name, card_name=card.name) self.event_type = '' + elif len([c for c in self.hand if (isinstance(c, cs.Mancato) and c.can_be_used_now) or (self.character.check(self.game, chars.CalamityJanet) and isinstance(c, cs.Bang)) or self.character.check(self.game, chd.ElenaFuente)]) == 0 and len([c for c in self.equipment if c.can_be_used_now and isinstance(c, cs.Mancato)]) == 0: + self.on_failed_response_cb() + if self.game: + self.game.responders_did_respond_resume_turn(did_lose=True) + if isinstance(card, tvosc.RitornoDiFiamma): + self.game.attack(self, self.attacker.name, card_name=card.name) else: self.pending_action = PendingAction.RESPOND self.notify_self() diff --git a/backend/tests/character_test.py b/backend/tests/character_test.py index 740f757..daaf109 100644 --- a/backend/tests/character_test.py +++ b/backend/tests/character_test.py @@ -297,8 +297,6 @@ def test_SlabTheKiller(): g.players[g.turn].play_card(0, g.players[(g.turn+1)%2].name) assert g.players[(g.turn+1)%2].pending_action == PendingAction.RESPOND g.players[(g.turn+1)%2].respond(0) - assert g.players[(g.turn+1)%2].pending_action == PendingAction.RESPOND - g.players[(g.turn+1)%2].respond(-1) assert g.players[(g.turn+1)%2].pending_action == PendingAction.WAIT assert g.players[(g.turn+1)%2].lives == 3 diff --git a/backend/tests/valley_of_shadows_test.py b/backend/tests/valley_of_shadows_test.py index 3768f76..c477ab2 100644 --- a/backend/tests/valley_of_shadows_test.py +++ b/backend/tests/valley_of_shadows_test.py @@ -5,6 +5,7 @@ from tests.dummy_socket import DummySocket from bang.deck import Deck from bang.game import Game from bang.players import Player, PendingAction +import bang.cards as cs # test UltimoGiro def test_ultimo_giro(): @@ -69,3 +70,73 @@ def test_fantasma(): pl.choose(0) assert pl.pending_action == PendingAction.PLAY assert len(fantasma_guy.equipment) == 1 and isinstance(fantasma_guy.equipment[0], Fantasma) + +# test SerpenteASonagli +def test_serpente_a_sonagli(): + sio = DummySocket() + g = Game('test', sio) + ps = [Player(f'p{i}', f'p{i}', sio) for i in range(3)] + for p in ps: + g.add_player(p) + g.start_game() + for p in ps: + p.available_characters = [Character('test_char', 4)] + p.set_character(p.available_characters[0].name) + p = g.players[g.turn] + serp = g.players[(g.turn+1)%3] + p.draw('') + p.hand = [SerpenteASonagli(0,0)] + assert len(p.hand) == 1 + p.play_card(0, serp.name) + assert len(p.hand) == 0 + assert len(serp.equipment) == 1 and isinstance(serp.equipment[0], SerpenteASonagli) + p.end_turn() + assert serp.pending_action == PendingAction.PICK + g.deck.cards[0] = Bang(Suit.SPADES, 5) + serp.pick() + assert serp.lives == 3 + serp.draw('') + serp.hand = [SerpenteASonagli(0,0)] + serp.play_card(0, g.players[(g.turn+1)%3].name) + assert len(serp.hand) == 0 + serp.end_turn() + assert g.players[g.turn].pending_action == PendingAction.PICK + g.deck.cards[0] = Bang(Suit.HEARTS, 5) + g.players[g.turn].pick() + assert g.players[g.turn].lives == 4 + +# test RitornoDiFiamma +def test_ritorno_di_fiamma(): + sio = DummySocket() + g = Game('test', sio) + g.expansions = ['the_valley_of_shadows'] + ps = [Player(f'p{i}', f'p{i}', sio) for i in range(3)] + for p in ps: + g.add_player(p) + g.start_game() + for p in ps: + p.available_characters = [Character('test_char', 4)] + p.set_character(p.available_characters[0].name) + p = g.players[g.turn] + p1 = g.players[(g.turn+1)%3] + p.draw('') + p.hand = [Bang(1, 1)] + p1.hand = [RitornoDiFiamma(0,0)] + p.play_card(0, p1.name) + assert len(p.hand) == 0 + assert len(p1.hand) == 1 + p1.respond(0) + assert len(p1.hand) == 0 + assert p.lives == 3 + p.end_turn() + p1.draw('') + p1.hand = [Bang(1, 1)] + p.equipment = [cs.Barile(0,0)] + p.hand = [RitornoDiFiamma(0,0)] + p1.play_card(0, p.name) + assert p.pending_action == PendingAction.PICK + g.deck.cards[0] = Bang(Suit.SPADES, 5) + p.pick() + assert p.pending_action == PendingAction.RESPOND + p.respond(0) + assert p1.lives == 3 From 30b3e826a02ce5420fe00ae84b28e861cbb2fc26 Mon Sep 17 00:00:00 2001 From: Alberto Xamin Date: Sat, 7 Jan 2023 12:03:23 +0000 Subject: [PATCH 21/36] add shotgun --- backend/bang/expansions/the_valley_of_shadows/cards.py | 3 +-- backend/bang/players.py | 4 ++++ frontend/src/components/Player.vue | 2 +- frontend/src/i18n/en.json | 3 ++- frontend/src/i18n/it.json | 3 ++- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/backend/bang/expansions/the_valley_of_shadows/cards.py b/backend/bang/expansions/the_valley_of_shadows/cards.py index 8c90d0b..b212d7f 100644 --- a/backend/bang/expansions/the_valley_of_shadows/cards.py +++ b/backend/bang/expansions/the_valley_of_shadows/cards.py @@ -56,7 +56,6 @@ class Shotgun(Card): def __init__(self, suit, number): super().__init__(suit, 'Shotgun', number, is_equipment=True, is_weapon=True, range=1) self.icon = '🔫' # Ogni volta che colpisci un giocatore deve scartare una carta - #TODO class Taglia(Card): def __init__(self, suit, number): @@ -196,7 +195,7 @@ def get_starting_deck() -> List[Card]: Fantasma(Suit.SPADES, 10), # Lemat(Suit.DIAMONDS, 4), SerpenteASonagli(Suit.HEARTS, 7), - # Shotgun(Suit.SPADES, 'K'), + Shotgun(Suit.SPADES, 'K'), # Taglia(Suit.CLUBS, 9), UltimoGiro(Suit.DIAMONDS, 8), Tomahawk(Suit.DIAMONDS, 'A'), diff --git a/backend/bang/players.py b/backend/bang/players.py index 269e3b5..28fe61b 100644 --- a/backend/bang/players.py +++ b/backend/bang/players.py @@ -1152,6 +1152,10 @@ class Player: self.sio.emit('chat_message', room=self.game.name, data=f'_special_el_gringo|{self.name}|{self.attacker.name}') self.attacker.notify_self() + if self.attacker and len(self.hand) > 0 and any((isinstance(c, tvosc.Shotgun) for c in self.attacker.equipment)): + c = self.hand.pop(randrange(0, len(self.hand))) + self.game.deck.scrap(c, True) + self.sio.emit('chat_message', room=self.game.name, data=f'_shotgun_scrap|{self.name}|{c.name}') if self.attacker and 'gold_rush' in self.game.expansions: if (isinstance(self.attacker, Player)): self.attacker.gold_nuggets += 1 diff --git a/frontend/src/components/Player.vue b/frontend/src/components/Player.vue index c673afd..f29f459 100644 --- a/frontend/src/components/Player.vue +++ b/frontend/src/components/Player.vue @@ -54,7 +54,7 @@ - + diff --git a/frontend/src/i18n/en.json b/frontend/src/i18n/en.json index 6f362d2..e0e00b9 100644 --- a/frontend/src/i18n/en.json +++ b/frontend/src/i18n/en.json @@ -132,7 +132,8 @@ "UnionPacific": "{0} played Union Pacific and draws 4 cards from the deck", "use_special": "{0} used the special ability of their character ({1})", "gold_rush_pay_discard": "{0} discarded {2} from {1}.", - "choose_emporio": "{0} has chosen {1} from General Store." + "choose_emporio": "{0} has chosen {1} from General Store.", + "shotgun_scrap": "When the shotgun hit {0} a card flew away from his hand ({1})" }, "foc": { "leggedelwest": "He must play this card on this turn if possible." diff --git a/frontend/src/i18n/it.json b/frontend/src/i18n/it.json index a90b083..0a84ce6 100644 --- a/frontend/src/i18n/it.json +++ b/frontend/src/i18n/it.json @@ -132,7 +132,8 @@ "UnionPacific": "{0} ha giocato Union Pacific e ha pescato 4 carte.", "use_special": "{0} ha usato l'abilità speciale del suo personaggio ({1})", "gold_rush_pay_discard": "{0} ha fatto scartare {2} a {1}.", - "choose_emporio": "{0} ha scelto {1} da Emporio." + "choose_emporio": "{0} ha scelto {1} da Emporio.", + "shotgun_scrap": "Quando lo shotgun ha colpito {0} gli ha tolto una carta ({1})" }, "foc": { "leggedelwest": "Ed è obbligato a usarla nel suo turno, se possibile" From 4958a2c7dc586a313c5cda8af2c748d133d37037 Mon Sep 17 00:00:00 2001 From: Alberto Xamin Date: Sat, 7 Jan 2023 12:03:55 +0000 Subject: [PATCH 22/36] tweak timer --- frontend/src/components/Chooser.vue | 25 ++++++++++++++++--------- frontend/src/components/Player.vue | 8 ++++---- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/frontend/src/components/Chooser.vue b/frontend/src/components/Chooser.vue index 22fe758..785144c 100644 --- a/frontend/src/components/Chooser.vue +++ b/frontend/src/components/Chooser.vue @@ -3,12 +3,12 @@

{{text}}

- +
-

{{remainingTime}}

{{hintText}}

-
{{realCancelText}}
+

{{remainingTime}}

+
{{realCancelText}} ({{remainingTime}})

{{desc}}

@@ -72,7 +72,15 @@ export default { this.select(this.cards[0]); window.clearInterval(this.intervalID); } - } + }, + internalCancel() { + if (this.intervalID) window.clearInterval(this.intervalID); + this.cancel(); + }, + internalSelect(card) { + if (this.intervalID) window.clearInterval(this.intervalID); + this.select(card); + }, }, mounted() { this.realCancelText = this.cancelText @@ -85,11 +93,10 @@ export default { if (this.playAudio) { (new Audio(show_sfx)).play(); } - if (this.timer > 0) { - this.remainingTime = this.timer; - this.intervalID = window.setInterval(() => { - this.countDown(); - }, 1000); + this.remainingTime = this.timer; + if (this.timer != 0 && this.remainingTime == this.timer) { + if (this.intervalID) window.clearInterval(this.intervalID); + this.intervalID = window.setInterval(this.countDown, 1000); } }, } diff --git a/frontend/src/components/Player.vue b/frontend/src/components/Player.vue index f29f459..39bdfdb 100644 --- a/frontend/src/components/Player.vue +++ b/frontend/src/components/Player.vue @@ -50,15 +50,15 @@ - - + + - + - + From 1ea91af237ed8e06a76b2539bec21c23a6dde92d Mon Sep 17 00:00:00 2001 From: Alberto Xamin Date: Sat, 7 Jan 2023 12:11:18 +0000 Subject: [PATCH 23/36] add taglia --- .../expansions/the_valley_of_shadows/cards.py | 15 +++++++++++++-- backend/bang/players.py | 5 +++++ frontend/src/i18n/en.json | 3 ++- frontend/src/i18n/it.json | 3 ++- 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/backend/bang/expansions/the_valley_of_shadows/cards.py b/backend/bang/expansions/the_valley_of_shadows/cards.py index b212d7f..cbf76f6 100644 --- a/backend/bang/expansions/the_valley_of_shadows/cards.py +++ b/backend/bang/expansions/the_valley_of_shadows/cards.py @@ -62,7 +62,18 @@ class Taglia(Card): super().__init__(suit, 'Taglia', number, is_equipment=True) self.need_target = True self.icon = '💰' # chiunque colpisca il giocatore con la taglia pesca una carta dal mazzo, si toglie solo con panico, cat balou, dalton - #TODO + + def play_card(self, player, against, _with=None): + if (player.game.check_event(ce.IlGiudice)): + return False + if against != None: + self.reset_card() + player.sio.emit('chat_message', room=player.game.name, + data=f'_play_card_against|{player.name}|{self.name}|{against}') + player.game.get_player_named(against).equipment.append(self) + player.game.get_player_named(against).notify_self() + return True + return False class UltimoGiro(Card): def __init__(self, suit, number): @@ -196,7 +207,7 @@ def get_starting_deck() -> List[Card]: # Lemat(Suit.DIAMONDS, 4), SerpenteASonagli(Suit.HEARTS, 7), Shotgun(Suit.SPADES, 'K'), - # Taglia(Suit.CLUBS, 9), + Taglia(Suit.CLUBS, 9), UltimoGiro(Suit.DIAMONDS, 8), Tomahawk(Suit.DIAMONDS, 'A'), # Sventagliata(Suit.SPADES, 2), diff --git a/backend/bang/players.py b/backend/bang/players.py index 28fe61b..6a956a7 100644 --- a/backend/bang/players.py +++ b/backend/bang/players.py @@ -1152,6 +1152,11 @@ class Player: self.sio.emit('chat_message', room=self.game.name, data=f'_special_el_gringo|{self.name}|{self.attacker.name}') self.attacker.notify_self() + if self.attacker and any((isinstance(c, tvosc.Taglia) for c in self.equipment)): + self.attacker.hand.append(self.game.deck.draw(True)) + self.sio.emit('chat_message', room=self.game.name, + data=f'_taglia_reward|{self.name}|{self.attacker.name}') + self.attacker.notify_self() if self.attacker and len(self.hand) > 0 and any((isinstance(c, tvosc.Shotgun) for c in self.attacker.equipment)): c = self.hand.pop(randrange(0, len(self.hand))) self.game.deck.scrap(c, True) diff --git a/frontend/src/i18n/en.json b/frontend/src/i18n/en.json index e0e00b9..95e36e7 100644 --- a/frontend/src/i18n/en.json +++ b/frontend/src/i18n/en.json @@ -133,7 +133,8 @@ "use_special": "{0} used the special ability of their character ({1})", "gold_rush_pay_discard": "{0} discarded {2} from {1}.", "choose_emporio": "{0} has chosen {1} from General Store.", - "shotgun_scrap": "When the shotgun hit {0} a card flew away from his hand ({1})" + "shotgun_scrap": "When the shotgun hit {0} a card flew away from his hand ({1})", + "taglia_reward": "{1} got a card from the bounty on {0}" }, "foc": { "leggedelwest": "He must play this card on this turn if possible." diff --git a/frontend/src/i18n/it.json b/frontend/src/i18n/it.json index 0a84ce6..cd1f5fb 100644 --- a/frontend/src/i18n/it.json +++ b/frontend/src/i18n/it.json @@ -133,7 +133,8 @@ "use_special": "{0} ha usato l'abilità speciale del suo personaggio ({1})", "gold_rush_pay_discard": "{0} ha fatto scartare {2} a {1}.", "choose_emporio": "{0} ha scelto {1} da Emporio.", - "shotgun_scrap": "Quando lo shotgun ha colpito {0} gli ha tolto una carta ({1})" + "shotgun_scrap": "Quando lo shotgun ha colpito {0} gli ha tolto una carta ({1})", + "taglia_reward": "{1} ha ottenuto ricompensa dalla taglia su {0}" }, "foc": { "leggedelwest": "Ed è obbligato a usarla nel suo turno, se possibile" From 60ef42f98af1fb2ac2615cffc4817ed731aaf407 Mon Sep 17 00:00:00 2001 From: Alberto Xamin Date: Mon, 9 Jan 2023 10:14:27 +0100 Subject: [PATCH 24/36] write errors in the chat during debug --- backend/server.py | 62 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 59 insertions(+), 3 deletions(-) diff --git a/backend/server.py b/backend/server.py index e443d00..137a3de 100644 --- a/backend/server.py +++ b/backend/server.py @@ -13,11 +13,16 @@ import requests from discord_webhook import DiscordWebhook from metrics import Metrics -Metrics.init() - -import sys +import sys +import traceback sys.setrecursionlimit(10**6) # this should prevents bots from stopping +import logging +logger = logging.basicConfig(filename='out.log', level='ERROR') +from functools import wraps + +Metrics.init() + sio = socketio.Server(cors_allowed_origins="*") static_files={ @@ -44,6 +49,22 @@ games: List[Game] = [] online_players = 0 blacklist: List[str] = [] +def send_to_debug(error): + for g in games: + if g.debug or any((p.is_admin() for p in g.players)): + sio.emit('chat_message', room=g.name, data={'color': f'red','text':json.dumps({'ERROR':error}), 'type':'json'}) + +def bang_handler(func): + @wraps(func) + def wrapper_func(*args, **kwargs): + try: + func(*args, **kwargs) + except Exception as e: + logging.exception(e) + print(traceback.format_exc()) + send_to_debug(traceback.format_exc()) + return wrapper_func + def advertise_lobbies(): sio.emit('lobbies', room='lobby', data=[{'name': g.name, 'players': len(g.players), 'locked': g.password != ''} for g in games if not g.started and len(g.players) < 10 and not g.is_hidden]) sio.emit('spectate_lobbies', room='lobby', data=[{'name': g.name, 'players': len(g.players), 'locked': g.password != ''} for g in games if g.started and not g.is_hidden]) @@ -51,6 +72,7 @@ def advertise_lobbies(): Metrics.send_metric('online_players', points=[online_players]) @sio.event +@bang_handler def connect(sid, environ): global online_players online_players += 1 @@ -60,11 +82,13 @@ def connect(sid, environ): Metrics.send_metric('online_players', points=[online_players]) @sio.event +@bang_handler def get_online_players(sid): global online_players sio.emit('players', room='lobby', data=online_players) @sio.event +@bang_handler def report(sid, text): print(f'New report from {sid}: {text}') ses: Player = sio.get_session(sid) @@ -85,6 +109,7 @@ def report(sid, text): print(f'New bug report, replay at https://bang.xamin.it/game?replay={key}') @sio.event +@bang_handler def set_username(sid, username): ses = sio.get_session(sid) if not isinstance(ses, Player): @@ -105,6 +130,7 @@ def set_username(sid, username): ses.game.notify_room() @sio.event +@bang_handler def get_me(sid, room): if isinstance(sio.get_session(sid), Player): sio.emit('me', data=sio.get_session(sid).name, room=sid) @@ -174,6 +200,7 @@ def get_me(sid, room): sio.get_session(sid).game.notify_room() @sio.event +@bang_handler def disconnect(sid): global online_players online_players -= 1 @@ -187,6 +214,7 @@ def disconnect(sid): Metrics.send_metric('online_players', points=[online_players]) @sio.event +@bang_handler def create_room(sid, room_name): if sio.get_session(sid).game == None: while len([g for g in games if g.name == room_name]): @@ -202,25 +230,30 @@ def create_room(sid, room_name): advertise_lobbies() @sio.event +@bang_handler def private(sid): g = sio.get_session(sid).game g.set_private() advertise_lobbies() @sio.event +@bang_handler def toggle_expansion(sid, expansion_name): g = sio.get_session(sid).game g.toggle_expansion(expansion_name) @sio.event +@bang_handler def toggle_comp(sid): sio.get_session(sid).game.toggle_competitive() @sio.event +@bang_handler def toggle_replace_with_bot(sid): sio.get_session(sid).game.toggle_disconnect_bot() @sio.event +@bang_handler def join_room(sid, room): room_name = room['name'] i = [g.name for g in games].index(room_name) @@ -250,6 +283,7 @@ Sockets for the status page """ @sio.event +@bang_handler def get_all_rooms(sid, deploy_key): if ('DEPLOY_KEY' in os.environ and deploy_key == os.environ['DEPLOY_KEY']) or sio.get_session(sid).is_admin(): sio.emit('all_rooms', room=sid, data=[{ @@ -266,11 +300,13 @@ def get_all_rooms(sid, deploy_key): } for g in games]) @sio.event +@bang_handler def kick(sid, data): if ('DEPLOY_KEY' in os.environ and data['key'] == os.environ['DEPLOY_KEY']) or sio.get_session(sid).is_admin(): sio.emit('kicked', room=data['sid']) @sio.event +@bang_handler def hide_toogle(sid, data): if ('DEPLOY_KEY' in os.environ and data['key'] == os.environ['DEPLOY_KEY']) or sio.get_session(sid).is_admin(): game = [g for g in games if g.name==data['room']] @@ -288,12 +324,14 @@ Sockets for the game """ @sio.event +@bang_handler def start_game(sid): ses: Player = sio.get_session(sid) ses.game.start_game() advertise_lobbies() @sio.event +@bang_handler def set_character(sid, name): ses: Player = sio.get_session(sid) ses.game.rpc_log.append(f'{ses.name};set_character;{name}') @@ -302,47 +340,55 @@ def set_character(sid, name): ses.set_character(name) @sio.event +@bang_handler def refresh(sid): ses: Player = sio.get_session(sid) ses.notify_self() @sio.event +@bang_handler def draw(sid, pile): ses: Player = sio.get_session(sid) ses.game.rpc_log.append(f'{ses.name};draw;{pile}') ses.draw(pile) @sio.event +@bang_handler def pick(sid): ses: Player = sio.get_session(sid) ses.game.rpc_log.append(f'{ses.name};pick') ses.pick() @sio.event +@bang_handler def end_turn(sid): ses: Player = sio.get_session(sid) ses.game.rpc_log.append(f'{ses.name};end_turn') ses.end_turn() @sio.event +@bang_handler def play_card(sid, data): ses: Player = sio.get_session(sid) ses.game.rpc_log.append(f'{ses.name};play_card;{json.dumps(data)}') ses.play_card(data['index'], data['against'], data['with']) @sio.event +@bang_handler def respond(sid, card_index): ses: Player = sio.get_session(sid) ses.game.rpc_log.append(f'{ses.name};respond;{card_index}') ses.respond(card_index) @sio.event +@bang_handler def choose(sid, card_index): ses: Player = sio.get_session(sid) ses.game.rpc_log.append(f'{ses.name};choose;{card_index}') ses.choose(card_index) @sio.event +@bang_handler def scrap(sid, card_index): ses: Player = sio.get_session(sid) ses.game.rpc_log.append(f'{ses.name};scrap;{card_index}') @@ -355,18 +401,21 @@ def special(sid, data): ses.special(data) @sio.event +@bang_handler def gold_rush_discard(sid): ses: Player = sio.get_session(sid) ses.game.rpc_log.append(f'{ses.name};gold_rush_discard;') ses.gold_rush_discard() @sio.event +@bang_handler def buy_gold_rush_card(sid, data:int): ses: Player = sio.get_session(sid) ses.game.rpc_log.append(f'{ses.name};buy_gold_rush_card;{data}') ses.buy_gold_rush_card(data) @sio.event +@bang_handler def chat_message(sid, msg, pl=None): ses: Player = sio.get_session(sid) if pl is None else pl ses.game.rpc_log.append(f'{ses.name};chat_message;{msg}') @@ -611,6 +660,7 @@ Sockets for the help screen """ @sio.event +@bang_handler def get_cards(sid): import bang.cards as c cards = c.get_starting_deck(['dodge_city']) @@ -623,12 +673,14 @@ def get_cards(sid): Metrics.send_metric('help_screen_viewed', points=[1]) @sio.event +@bang_handler def get_characters(sid): import bang.characters as ch cards = ch.all_characters(['dodge_city', 'gold_rush']) sio.emit('characters_info', room=sid, data=json.dumps(cards, default=lambda o: o.__dict__)) @sio.event +@bang_handler def get_highnooncards(sid): import bang.expansions.high_noon.card_events as ceh chs = [] @@ -637,6 +689,7 @@ def get_highnooncards(sid): sio.emit('highnooncards_info', room=sid, data=json.dumps(chs, default=lambda o: o.__dict__)) @sio.event +@bang_handler def get_foccards(sid): import bang.expansions.fistful_of_cards.card_events as ce chs = [] @@ -645,6 +698,7 @@ def get_foccards(sid): sio.emit('foccards_info', room=sid, data=json.dumps(chs, default=lambda o: o.__dict__)) @sio.event +@bang_handler def get_goldrushcards(sid): import bang.expansions.gold_rush.shop_cards as grc cards = grc.get_cards() @@ -656,6 +710,7 @@ def get_goldrushcards(sid): sio.emit('goldrushcards_info', room=sid, data=json.dumps(cards, default=lambda o: o.__dict__)) @sio.event +@bang_handler def get_valleyofshadowscards(sid): import bang.expansions.the_valley_of_shadows.cards as tvos cards = tvos.get_starting_deck() @@ -667,6 +722,7 @@ def get_valleyofshadowscards(sid): sio.emit('valleyofshadows_info', room=sid, data=json.dumps(cards, default=lambda o: o.__dict__)) @sio.event +@bang_handler def discord_auth(sid, data): res = requests.post('https://discord.com/api/oauth2/token', data={ 'client_id': '1059452581027532880', From 0470e20cbbea35c0a209dd8b618ff99e0fd0f4f5 Mon Sep 17 00:00:00 2001 From: Alberto Xamin Date: Mon, 9 Jan 2023 10:36:46 +0000 Subject: [PATCH 25/36] pylint happy --- backend/server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/server.py b/backend/server.py index 137a3de..275b9ac 100644 --- a/backend/server.py +++ b/backend/server.py @@ -18,7 +18,7 @@ import traceback sys.setrecursionlimit(10**6) # this should prevents bots from stopping import logging -logger = logging.basicConfig(filename='out.log', level='ERROR') +logging.basicConfig(filename='out.log', level='ERROR') from functools import wraps Metrics.init() From e03883bf7cf5dd7b9aed02e4554554f5c428c387 Mon Sep 17 00:00:00 2001 From: Alberto Xamin Date: Mon, 9 Jan 2023 12:52:47 +0000 Subject: [PATCH 26/36] reduce allocations --- backend/bang/expansions/dodge_city/cards.py | 2 +- .../bang/expansions/dodge_city/characters.py | 4 +- backend/bang/game.py | 16 ++-- backend/bang/players.py | 86 +++++++++---------- backend/server.py | 10 +-- 5 files changed, 59 insertions(+), 59 deletions(-) diff --git a/backend/bang/expansions/dodge_city/cards.py b/backend/bang/expansions/dodge_city/cards.py index 8dd7b49..af0f7aa 100644 --- a/backend/bang/expansions/dodge_city/cards.py +++ b/backend/bang/expansions/dodge_city/cards.py @@ -75,7 +75,7 @@ class Rissa(CatBalou): def play_card(self, player, against, _with): if _with != None: - if len([p for p in player.game.players if p != player and (len(p.hand)+len(p.equipment)) > 0]) == 0: + if not any((p != player and (len(p.hand)+len(p.equipment)) > 0 for p in player.game.players)): return False #se sono qui vuol dire che ci sono giocatori con carte in mano oltre a me player.rissa_targets = [] diff --git a/backend/bang/expansions/dodge_city/characters.py b/backend/bang/expansions/dodge_city/characters.py index d2c96de..0e1d3cd 100644 --- a/backend/bang/expansions/dodge_city/characters.py +++ b/backend/bang/expansions/dodge_city/characters.py @@ -90,9 +90,9 @@ class ChuckWengam(Character): if player.lives > 1 and player.is_my_turn: import bang.expansions.gold_rush.shop_cards as grc player.lives -= 1 - if len([c for c in player.gold_rush_equipment if isinstance(c, grc.Talismano)]) > 0: + if any((isinstance(c, grc.Talismano) for c in player.gold_rush_equipment)): player.gold_nuggets += 1 - if len([c for c in player.gold_rush_equipment if isinstance(c, grc.Stivali)]) > 0: + if any((isinstance(c, grc.Stivali) for c in player.gold_rush_equipment)): player.hand.append(player.game.deck.draw(True)) player.hand.append(player.game.deck.draw(True)) player.hand.append(player.game.deck.draw(True)) diff --git a/backend/bang/game.py b/backend/bang/game.py index 5076096..be69728 100644 --- a/backend/bang/game.py +++ b/backend/bang/game.py @@ -173,7 +173,7 @@ class Game: def notify_room(self, sid=None): - if len([p for p in self.players if p.character == None]) != 0 or sid: + if any((p.character == None for p in self.players)) or sid: self.sio.emit('room', room=self.name if not sid else sid, data={ 'name': self.name, 'started': self.started, @@ -243,7 +243,7 @@ class Game: def notify_character_selection(self): self.notify_room() - if len([p for p in self.players if p.character == None]) == 0: + if not any((p.character == None for p in self.players)): for i in range(len(self.players)): print(self.name, self.players[i].name, self.players[i].character) self.sio.emit('chat_message', room=self.name, data=f'_choose_character|{self.players[i].name}|{self.players[i].character.name}') @@ -443,11 +443,11 @@ class Game: print(f'{self.name}: stop roulette') target_pl.lives -= 1 target_pl.heal_if_needed() - if len([c for c in target_pl.gold_rush_equipment if isinstance(c, grc.Talismano)]) > 0: + if any((isinstance(c, grc.Talismano) for c in target_pl.gold_rush_equipment)): target_pl.gold_nuggets += 1 if target_pl.character.check(self, grch.SimeonPicos): target_pl.gold_nuggets += 1 - if len([c for c in target_pl.gold_rush_equipment if isinstance(c, grc.Stivali)]) > 0: + if any((isinstance(c, grc.Stivali) for c in target_pl.gold_rush_equipment)): target_pl.hand.append(self.deck.draw(True)) target_pl.notify_self() self.is_russian_roulette_on = False @@ -617,9 +617,9 @@ class Game: player.game = None if self.disconnect_bot and self.started: player.is_bot = True - if len([p for p in self.players if not p.is_bot]) == 0: + if not any((not p.is_bot for p in self.players)): eventlet.sleep(5) - if len([p for p in self.players if not p.is_bot]) == 0: + if not any((not p.is_bot for p in self.players)): print(f'{self.name}: no players left in game, shutting down') self.shutting_down = True self.players = [] @@ -637,7 +637,7 @@ class Game: # else: # player.lives = 0 # self.players.remove(player) - if len([p for p in self.players if not p.is_bot]) == 0: + if not any((not p.is_bot for p in self.players)): print(f'{self.name}: no players left in game, shutting down') self.shutting_down = True self.players = [] @@ -654,7 +654,7 @@ class Game: if player.character and player.role: if not self.is_replay: Metrics.send_metric('player_death', points=[1], tags=[f"char:{player.character.name}", f"role:{player.role.name}"]) - if len([c for c in player.gold_rush_equipment if isinstance(c, grc.Ricercato)]) > 0 and player.attacker and player.attacker in self.players: + if any((isinstance(c, grc.Ricercato) for c in player.gold_rush_equipment)) and player.attacker and player.attacker in self.players: player.attacker.gold_nuggets += 1 player.attacker.hand.append(self.deck.draw(True)) player.attacker.hand.append(self.deck.draw(True)) diff --git a/backend/bang/players.py b/backend/bang/players.py index 6a956a7..b4e9b46 100644 --- a/backend/bang/players.py +++ b/backend/bang/players.py @@ -237,7 +237,7 @@ class Player: self.hand.append(self.game.deck.draw(True)) if self.lives <= 0 and self.max_lives > 0 and not self.is_dead: print('dying, attacker', self.attacker) - if self.gold_nuggets >= 2 and len([c for c in self.gold_rush_equipment if isinstance(c, grc.Zaino)]) > 0: + if self.gold_nuggets >= 2 and any((isinstance(c, grc.Zaino) for c in self.gold_rush_equipment)): for i in range(len(self.gold_rush_equipment)): if isinstance(self.gold_rush_equipment[i], grc.Zaino): self.gold_rush_equipment[i].play_card(self, None) @@ -266,7 +266,7 @@ class Player: ser['attacker'] = self.attacker.name ser['sight'] = self.get_sight() ser['sight_extra'] = self.get_sight(False) -1 - ser['can_gold_rush_discard'] = len([p for p in self.game.get_alive_players() if p != self and len([e for e in p.gold_rush_equipment if e.number <= self.gold_nuggets + 1]) > 0]) > 0 + ser['can_gold_rush_discard'] = any((p != self and any((e.number <= self.gold_nuggets + 1 for e in p.gold_rush_equipment)) for p in self.game.get_alive_players())) if self.character: ser['gold_rush_discount'] = 1 if self.character.check(self.game, grch.PrettyLuzena) and self.special_use_count < 1 else 0 ser['lives'] = max(ser['lives'], 0) @@ -368,7 +368,7 @@ class Player: return break maxcards = self.lives if not self.character.check(self.game, chd.SeanMallory) else 10 - if maxcards == self.lives and len([c for c in self.gold_rush_equipment if isinstance(c, grc.Cinturone)]) > 0: + if maxcards == self.lives and any((isinstance(c, grc.Cinturone) for c in self.gold_rush_equipment)): maxcards = 8 if len(self.hand) > maxcards: self.game.rpc_log.append(f'{self.name};scrap;{0}') @@ -434,11 +434,11 @@ class Player: self.bang_used = 0 if self.game.check_event(ceh.MezzogiornoDiFuoco): self.lives -= 1 - if len([c for c in self.gold_rush_equipment if isinstance(c, grc.Talismano)]) > 0: + if any((isinstance(c, grc.Talismano) for c in self.gold_rush_equipment)): self.gold_nuggets += 1 if self.character.check(self.game, grch.SimeonPicos): self.gold_nuggets += 1 - if len([c for c in self.gold_rush_equipment if isinstance(c, grc.Stivali)]) > 0: + if any((isinstance(c, grc.Stivali) for c in self.gold_rush_equipment)): self.hand.append(self.game.deck.draw(True)) if self.character.check(self.game, chars.BartCassidy) and self.lives > 0: self.hand.append(self.game.deck.draw(True)) @@ -490,7 +490,7 @@ class Player: self.choose_text = 'choose_cecchino' self.pending_action = PendingAction.CHOOSE self.notify_self() - elif self.is_my_turn and self.pending_action == PendingAction.PLAY and pile == 'event' and self.game.check_event(ce.Rimbalzo) and len([c for c in self.hand if c.name == cs.Bang(0,0).name]) > 0: + elif self.is_my_turn and self.pending_action == PendingAction.PLAY and pile == 'event' and self.game.check_event(ce.Rimbalzo) and any((c.name == cs.Bang(0,0).name for c in self.hand)): self.available_cards = [{ 'name': p.name, 'icon': p.role.icon if(self.game.initial_players == 3) else '⭐️' if isinstance(p.role, r.Sheriff) else '🤠', @@ -532,7 +532,7 @@ class Player: self.pending_action = PendingAction.PLAY num = 2 if not self.character.check(self.game, chd.BillNoface) else self.max_lives-self.lives+1 if self.character.check(self.game, chd.PixiePete): num += 1 - if (len([c for c in self.gold_rush_equipment if isinstance(c, grc.Piccone)]) > 0): num += 1 + if (any((isinstance(c, grc.Piccone) for c in self.gold_rush_equipment))): num += 1 if self.game.check_event(ceh.IlTreno) or (self.is_ghost and self.game.check_event(ceh.CittaFantasma)): num += 1 elif self.game.check_event(ceh.Sete): num -= 1 for i in range(num): @@ -574,7 +574,7 @@ class Player: if self.pending_action != PendingAction.PICK: return pickable_cards = 1 + self.character.pick_mod - if len([c for c in self.gold_rush_equipment if isinstance(c, grc.FerroDiCavallo)]) > 0: + if any((isinstance(c, grc.FerroDiCavallo) for c in self.gold_rush_equipment)): pickable_cards += 1 if self.is_my_turn and self.attacker == None: for i in range(len(self.equipment)): @@ -587,11 +587,11 @@ class Player: data=f'_flipped|{self.name}|{picked.name}|{picked.num_suit()}') if picked.check_suit(self.game, [cs.Suit.SPADES]) and 2 <= picked.number <= 9 and pickable_cards == 0: self.lives -= 3 - if len([c for c in self.gold_rush_equipment if isinstance(c, grc.Talismano)]) > 0: + if any((isinstance(c, grc.Talismano) for c in self.gold_rush_equipment)): self.gold_nuggets += 3 if self.character.check(self.game, grch.SimeonPicos): self.gold_nuggets += 3 - if len([c for c in self.gold_rush_equipment if isinstance(c, grc.Stivali)]) > 0: + if any((isinstance(c, grc.Stivali) for c in self.gold_rush_equipment)): self.hand.append(self.game.deck.draw()) self.hand.append(self.game.deck.draw()) self.hand.append(self.game.deck.draw()) @@ -694,7 +694,7 @@ class Player: print(self.name, 'is playing ', card, ' against:', against, ' with:', _with) did_play_card = False event_blocks_card = (self.game.check_event(ce.IlGiudice) and (card.is_equipment or (card.usable_next_turn and not card.can_be_used_now))) or (self.game.check_event(ce.Lazo) and card.usable_next_turn and card.can_be_used_now) or ((self.game.check_event(ceh.Manette) and card.suit != self.committed_suit_manette) and not (card.usable_next_turn and card.can_be_used_now)) - if not(against != None and (self.game.get_player_named(against).character.check(self.game, chd.ApacheKid) or len([c for c in self.game.get_player_named(against).gold_rush_equipment if isinstance(c, grc.Calumet)]) > 0) and card.check_suit(self.game, [cs.Suit.DIAMONDS])) or (isinstance(card, grc.ShopCard) and card.kind == grc.ShopCardKind.BLACK) and not event_blocks_card: + if not(against != None and (self.game.get_player_named(against).character.check(self.game, chd.ApacheKid) or any((isinstance(c, grc.Calumet) for c in self.game.get_player_named(against).gold_rush_equipment))) and card.check_suit(self.game, [cs.Suit.DIAMONDS])) or (isinstance(card, grc.ShopCard) and card.kind == grc.ShopCardKind.BLACK) and not event_blocks_card: if (against == self.name and not isinstance(card, csd.Tequila) and not isinstance(card, cs.Panico) and not isinstance(card, cs.CatBalou)) or event_blocks_card: did_play_card = False else: @@ -754,7 +754,7 @@ class Player: elif self.choose_text == 'choose_ricercato': player = self.game.get_player_named(self.available_cards[card_index]['name']) player.sio.emit('chat_message', room=player.game.name, data=f'_play_card_against|{self.name}|Ricercato|{player.name}') - if len([c for c in player.gold_rush_equipment if isinstance(c, grc.Ricercato)]) > 0: + if any((isinstance(c, grc.Ricercato) for c in player.gold_rush_equipment)): self.game.deck.shop_deck.append(grc.Ricercato()) else: player.gold_rush_equipment.append(grc.Ricercato()) @@ -846,11 +846,11 @@ class Player: player = self.game.get_player_named(self.available_cards[card_index]['name']) player.lives += 1 self.lives -= 1 - if len([c for c in self.gold_rush_equipment if isinstance(c, grc.Talismano)]) > 0: + if any((isinstance(c, grc.Talismano) for c in self.gold_rush_equipment)): self.gold_nuggets += 1 if self.character.check(self.game, grch.SimeonPicos): self.gold_nuggets += 1 - if len([c for c in self.gold_rush_equipment if isinstance(c, grc.Stivali)]) > 0: + if any((isinstance(c, grc.Stivali) for c in self.gold_rush_equipment)): self.hand.append(self.game.deck.draw()) player.notify_self() self.sio.emit('chat_message', room=self.game.name, data=f'_fratelli_sangue|{self.name}|{player.name}') @@ -930,7 +930,7 @@ class Player: self.hand.append(card) pickable_stop = 1 if self.game.check_event(ceh.Sete): pickable_stop += 1 - if self.game.check_event(ceh.IlTreno) or len([c for c in self.gold_rush_equipment if isinstance(c, grc.Piccone)]) > 0: + if self.game.check_event(ceh.IlTreno) or any((isinstance(c, grc.Piccone) for c in self.gold_rush_equipment)): pickable_stop -= 1 if len(self.available_cards) == pickable_stop: if len(self.available_cards) > 0: #la carta non scelta la rimettiamo in cima al mazzo @@ -938,7 +938,7 @@ class Player: if len(self.available_cards) > 0: #se sono rimaste carte le scartiamo self.game.deck.scrap(self.available_cards.pop()) #se c'è sia treno che piccone pesco un'altra carta - if self.game.check_event(ceh.IlTreno) and len([c for c in self.gold_rush_equipment if isinstance(c, grc.Piccone)]) > 0: + if self.game.check_event(ceh.IlTreno) and any((isinstance(c, grc.Piccone) for c in self.gold_rush_equipment)): self.hand.append(self.game.deck.draw()) self.is_drawing = False self.pending_action = PendingAction.PLAY @@ -954,7 +954,7 @@ class Player: #legge del west non si applica perchè la seconda carta viene scartata if self.game.check_event(ceh.IlTreno): self.hand.append(self.game.deck.draw()) - if len([c for c in self.gold_rush_equipment if isinstance(c, grc.Piccone)]) > 0: + if any((isinstance(c, grc.Piccone) for c in self.gold_rush_equipment)): self.hand.append(self.game.deck.draw()) self.gold_nuggets += 1 self.is_drawing = False @@ -978,9 +978,9 @@ class Player: def barrel_pick(self): pickable_cards = 1 + self.character.pick_mod - if len([c for c in self.gold_rush_equipment if isinstance(c, grc.FerroDiCavallo)]) > 0: + if any((isinstance(c, grc.FerroDiCavallo) for c in self.gold_rush_equipment)): pickable_cards += 1 - if len([c for c in self.equipment if isinstance(c, cs.Barile)]) > 0 and self.character.check(self.game, chars.Jourdonnais): + if any((isinstance(c, cs.Barile) for c in self.equipment)) and self.character.check(self.game, chars.Jourdonnais): pickable_cards = 2 while pickable_cards > 0: pickable_cards -= 1 @@ -994,8 +994,8 @@ class Player: if self.mancato_needed <= 0: self.game.responders_did_respond_resume_turn(did_lose=False) return - if not self.game.is_competitive and len([c for c in self.hand if isinstance(c, cs.Mancato) or (self.character.check(self.game, chars.CalamityJanet) and isinstance(c, cs.Bang)) or self.character.check(self.game, chd.ElenaFuente)]) == 0\ - and len([c for c in self.equipment if c.can_be_used_now and isinstance(c, cs.Mancato)]) == 0: + if not self.game.is_competitive and not any((isinstance(c, cs.Mancato) or (self.character.check(self.game, chars.CalamityJanet) and isinstance(c, cs.Bang)) or self.character.check(self.game, chd.ElenaFuente) for c in self.hand))\ + and not any((c.can_be_used_now and isinstance(c, cs.Mancato) for c in self.equipment)): self.take_damage_response() self.game.responders_did_respond_resume_turn(did_lose=True) else: @@ -1008,9 +1008,9 @@ class Player: def barrel_pick_no_dmg(self): pickable_cards = 1 + self.character.pick_mod - if len([c for c in self.equipment if isinstance(c, cs.Barile)]) > 0 and self.character.check(self.game, chars.Jourdonnais): + if any((isinstance(c, cs.Barile) for c in self.equipment)) and self.character.check(self.game, chars.Jourdonnais): pickable_cards = 2 - if len([c for c in self.gold_rush_equipment if isinstance(c, grc.FerroDiCavallo)]) > 0: + if any((isinstance(c, grc.FerroDiCavallo) for c in self.gold_rush_equipment)): pickable_cards += 1 while pickable_cards > 0: pickable_cards -= 1 @@ -1024,8 +1024,8 @@ class Player: if self.mancato_needed <= 0: self.game.responders_did_respond_resume_turn(did_lose=False) return - if not self.game.is_competitive and len([c for c in self.hand if isinstance(c, cs.Mancato) or (self.character.check(self.game, chars.CalamityJanet) and isinstance(c, cs.Bang)) or self.character.check(self.game, chd.ElenaFuente)]) == 0\ - and len([c for c in self.equipment if c.can_be_used_now and isinstance(c, cs.Mancato)]) == 0: + if not self.game.is_competitive and not any((isinstance(c, cs.Mancato) or (self.character.check(self.game, chars.CalamityJanet) and isinstance(c, cs.Bang)) or self.character.check(self.game, chd.ElenaFuente) for c in self.hand))\ + and not any((c.can_be_used_now and isinstance(c, cs.Mancato) for c in self.equipment)): self.take_no_damage_response() self.game.responders_did_respond_resume_turn(did_lose=True) else: @@ -1048,9 +1048,9 @@ class Player: for i in range(len(self.equipment)): if self.equipment[i].can_be_used_now: print('usable', self.equipment[i]) - if not self.game.is_competitive and len([c for c in self.equipment if isinstance(c, cs.Barile)]) == 0 and not self.character.check(self.game, chars.Jourdonnais)\ - and len([c for c in self.hand if (isinstance(c, cs.Mancato) and c.can_be_used_now) or (self.character.check(self.game, chars.CalamityJanet) and isinstance(c, cs.Bang)) or self.character.check(self.game, chd.ElenaFuente)]) == 0\ - and len([c for c in self.equipment if c.can_be_used_now and isinstance(c, cs.Mancato)]) == 0: + if not self.game.is_competitive and not any((isinstance(c, cs.Barile) for c in self.equipment)) and not self.character.check(self.game, chars.Jourdonnais)\ + and not any(((isinstance(c, cs.Mancato) and c.can_be_used_now) or (self.character.check(self.game, chars.CalamityJanet) and isinstance(c, cs.Bang)) or self.character.check(self.game, chd.ElenaFuente) for c in self.hand))\ + and not any((c.can_be_used_now and isinstance(c, cs.Mancato) for c in self.equipment)): print('Cant defend') if not no_dmg: self.take_damage_response() @@ -1058,7 +1058,7 @@ class Player: self.take_no_damage_response() return False else: - if ((not self.game.check_event(ce.Lazo) and len([c for c in self.equipment if isinstance(c, cs.Barile)]) > 0) \ + if ((not self.game.check_event(ce.Lazo) and any((isinstance(c, cs.Barile) for c in self.equipment))) \ and not (self.game.players[self.game.turn].character.check(self.game, chd.BelleStar) and isinstance(attacker, Player))) \ or self.character.check(self.game, chars.Jourdonnais): #se ho un barile e non c'è lazo e non mi sta attaccando Belle Star o se sono Jourdonnais print('has barrel') @@ -1094,8 +1094,8 @@ class Player: def get_indians(self, attacker): self.attacker = attacker self.attacking_card = "Indiani!" - if self.character.check(self.game, chd.ApacheKid) or len([c for c in self.gold_rush_equipment if isinstance(c, grc.Calumet)]) > 0: return False - if not self.game.is_competitive and len([c for c in self.hand if isinstance(c, cs.Bang) or (self.character.check(self.game, chars.CalamityJanet) and isinstance(c, cs.Mancato))]) == 0: + if self.character.check(self.game, chd.ApacheKid) or any((isinstance(c, grc.Calumet) for c in self.gold_rush_equipment)): return False + if not self.game.is_competitive and not any((isinstance(c, cs.Bang) or (self.character.check(self.game, chars.CalamityJanet) and isinstance(c, cs.Mancato)) for c in self.hand)): print('Cant defend') self.take_damage_response() return False @@ -1112,7 +1112,7 @@ class Player: def get_dueled(self, attacker): self.attacker = attacker self.attacking_card = "Duello" - if (self.game.check_event(ceh.Sermone) and self.is_my_turn) or (not self.game.is_competitive and len([c for c in self.hand if isinstance(c, cs.Bang) or (self.character.check(self.game, chars.CalamityJanet) and isinstance(c, cs.Mancato))]) == 0): + if (self.game.check_event(ceh.Sermone) and self.is_my_turn) or (not self.game.is_competitive and not any((isinstance(c, cs.Bang) or (self.character.check(self.game, chars.CalamityJanet) and isinstance(c, cs.Mancato)) for c in self.hand))): print('Cant defend') self.take_damage_response() self.game.responders_did_respond_resume_turn(did_lose=True) @@ -1127,7 +1127,7 @@ class Player: return True def heal_if_needed(self): - while self.lives <= 0 and len(self.game.get_alive_players()) > 2 and len([c for c in self.hand if isinstance(c, cs.Birra)]) > 0 and not self.game.check_event(ceh.IlReverendo): + while self.lives <= 0 and len(self.game.get_alive_players()) > 2 and any((isinstance(c, cs.Birra) for c in self.hand)) and not self.game.check_event(ceh.IlReverendo): for i in range(len(self.hand)): if isinstance(self.hand[i], cs.Birra): if self.character.check(self.game, chd.MollyStark) and not self.is_my_turn: @@ -1165,11 +1165,11 @@ class Player: if (isinstance(self.attacker, Player)): self.attacker.gold_nuggets += 1 self.attacker.notify_self() - if len([c for c in self.gold_rush_equipment if isinstance(c, grc.Talismano)]) > 0: + if any((isinstance(c, grc.Talismano) for c in self.gold_rush_equipment)): self.gold_nuggets += 1 if self.character.check(self.game, grch.SimeonPicos): self.gold_nuggets += 1 - if len([c for c in self.gold_rush_equipment if isinstance(c, grc.Stivali)]) > 0: + if any((isinstance(c, grc.Stivali) for c in self.gold_rush_equipment)): self.hand.append(self.game.deck.draw(True)) self.heal_if_needed() self.mancato_needed = 0 @@ -1300,7 +1300,7 @@ class Player: 'avatar': p.avatar, 'alt_text': ''.join(['🎴️'] * len(p.gold_rush_equipment)), 'noDesc': True - } for p in self.game.get_alive_players() if p != self and len([e for e in p.gold_rush_equipment if e.number + 1 <= self.gold_nuggets]) > 0] + } for p in self.game.get_alive_players() if p != self and any((e.number + 1 <= self.gold_nuggets for e in p.gold_rush_equipment))] self.available_cards.append({'icon': '❌', 'noDesc': True}) self.choose_text = 'gold_rush_discard' self.pending_action = PendingAction.CHOOSE @@ -1328,22 +1328,22 @@ class Player: card = must_be_used_cards[0] print(f'Legge del west card: {card.name}') print(self.has_played_bang and not (any((isinstance(c, cs.Volcanic) for c in self.equipment)) and type(card) == type(cs.Bang))) - if card.suit == cs.Suit.DIAMONDS and card.need_target and len([p for p in self.game.get_alive_players() if (not p.character.check(self.game, chd.ApacheKid) and not any((isinstance(c, grc.Calumet) for c in p.gold_rush_equipment)))]) == 0: + if card.suit == cs.Suit.DIAMONDS and card.need_target and not any(((not p.character.check(self.game, chd.ApacheKid) and not any((isinstance(c, grc.Calumet) for c in p.gold_rush_equipment))) for p in self.game.get_alive_players())): if isinstance(card, cs.Bang): return True else: return len(self.equipment) == 0 # se non ho carte equipaggiamento - elif (isinstance(card, cs.Bang) or (isinstance(card, cs.Mancato) and self.character.check(self.game, chars.CalamityJanet))) and self.has_played_bang and not any((isinstance(c, cs.Volcanic) for c in self.equipment)) or len([p for p in self.game.get_visible_players(self) if self.get_sight() >= p['dist']]) == 0: + elif (isinstance(card, cs.Bang) or (isinstance(card, cs.Mancato) and self.character.check(self.game, chars.CalamityJanet))) and self.has_played_bang and not any((isinstance(c, cs.Volcanic) for c in self.equipment)) or not any((self.get_sight() >= p['dist'] for p in self.game.get_visible_players(self))): return True elif isinstance(card, cs.Mancato) or (card.need_with and len(self.hand) < 2): return True - elif isinstance(card, cs.Panico) and len([p for p in self.game.get_visible_players(self) if self.get_sight(False) >= p['dist']]) == 0 and len(self.equipment) == 0: + elif isinstance(card, cs.Panico) and not any((self.get_sight(False) >= p['dist'] for p in self.game.get_visible_players(self))) and len(self.equipment) == 0: return True - elif isinstance(card, csd.Pugno) and len([p for p in self.game.get_visible_players(self) if self.get_sight(False) >= p['dist']]) == 0: + elif isinstance(card, csd.Pugno) and not any((self.get_sight(False) >= p['dist'] for p in self.game.get_visible_players(self))): return True - elif isinstance(card, cs.Prigione) and len([p for p in self.game.get_visible_players(self) if not p['is_sheriff']]) == 0: + elif isinstance(card, cs.Prigione) and not any((not p['is_sheriff'] for p in self.game.get_visible_players(self))): return True - elif not card.is_weapon and len([c for c in self.equipment if c.name == card.name]) > 0: + elif not card.is_weapon and any((c.name == card.name for c in self.equipment)): return True return False return True @@ -1353,7 +1353,7 @@ class Player: if not self.is_my_turn and not forced: return maxcards = self.lives if not self.character.check(self.game, chd.SeanMallory) else 10 - if maxcards == self.lives and len([c for c in self.gold_rush_equipment if isinstance(c, grc.Cinturone)]) > 0: + if maxcards == self.lives and any((isinstance(c, grc.Cinturone) for c in self.gold_rush_equipment)): maxcards = 8 if len(self.hand) > maxcards and not forced: print(f"{self.name}: I have to many cards in my hand and I can't end the turn") diff --git a/backend/server.py b/backend/server.py index 275b9ac..d2c90da 100644 --- a/backend/server.py +++ b/backend/server.py @@ -121,7 +121,7 @@ def set_username(sid, username): username = username["name"] print(f'{sid} changed username to {username}') prev = ses.name - if ses.game and len([p for p in ses.game.players if p.name == username]) > 0: + if ses.game and any((p.name == username for p in ses.game.players)): ses.name = f"{username}_{random.randint(0,100)}" else: ses.name = username @@ -157,7 +157,7 @@ def get_me(sid, room): join_room(sid, room) elif len(de_games) == 1 and de_games[0].started: print('room exists') - if room['username'] != None and any((p.name == room['username'] for p in de_games[0].players if p.is_bot)): + if room['username'] != None and any((p.name == room['username'] for p in de_games[0].players if (p.is_bot or (dt != None and p.discord_token == dt)))): print('getting inside the bot') bot = [p for p in de_games[0].players if p.is_bot and p.name == room['username'] ][0] bot.sid = sid @@ -217,7 +217,7 @@ def disconnect(sid): @bang_handler def create_room(sid, room_name): if sio.get_session(sid).game == None: - while len([g for g in games if g.name == room_name]): + while any((g.name == room_name for g in games)): room_name += f'_{random.randint(0,100)}' sio.leave_room(sid, 'lobby') sio.enter_room(sid, room_name) @@ -263,7 +263,7 @@ def join_room(sid, room): print(f'{sid} joined a room named {room_name}') sio.leave_room(sid, 'lobby') sio.enter_room(sid, room_name) - while len([p for p in games[i].players if p.name == sio.get_session(sid).name]): + while any((p.name == sio.get_session(sid).name and not p.is_bot for p in games[i].players)): sio.get_session(sid).name += f'_{random.randint(0,100)}' sio.emit('me', data=sio.get_session(sid).name, room=sid) games[i].add_player(sio.get_session(sid)) @@ -639,7 +639,7 @@ def chat_message(sid, msg, pl=None): ses.was_player = True ses.bot_spin() elif '/arcadekick' in msg and ses.game.started: - if len([p for p in ses.game.players if p.pending_action != PendingAction.WAIT]) == 0: + if not any((p.pending_action != PendingAction.WAIT for p in ses.game.players)): sio.emit('chat_message', room=ses.game.name, data={'color': f'','text':f'KICKING THE ARCADE CABINET'}) ses.game.next_turn() else: From 8a622def7aa3a99024efe2c14efe52708ecb1514 Mon Sep 17 00:00:00 2001 From: Alberto Xamin Date: Mon, 9 Jan 2023 13:04:47 +0000 Subject: [PATCH 27/36] even less allocations --- backend/bang/players.py | 6 +++--- backend/server.py | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/backend/bang/players.py b/backend/bang/players.py index b4e9b46..f7e025b 100644 --- a/backend/bang/players.py +++ b/backend/bang/players.py @@ -448,7 +448,7 @@ class Player: return self.notify_self() #non è un elif perchè vera custer deve fare questo poi cambiare personaggio - if self.game.check_event(ce.FratelliDiSangue) and self.lives > 1 and not self.is_giving_life and len([p for p in self.game.get_alive_players() if p != self and p.lives < p.max_lives]): + if self.game.check_event(ce.FratelliDiSangue) and self.lives > 1 and not self.is_giving_life and sum(p != self and p.lives < p.max_lives for p in self.game.get_alive_players()): self.available_cards = [{ 'name': p.name, 'icon': p.role.icon if(self.game.initial_players == 3) else '⭐️' if isinstance(p.role, r.Sheriff) else '🤠', @@ -477,7 +477,7 @@ class Player: self.notify_self() def draw(self, pile): - if self.is_my_turn and self.pending_action == PendingAction.PLAY and pile == 'event' and self.game.check_event(ce.Cecchino) and len([c for c in self.hand if c.name == cs.Bang(0,0).name]) >= 2: + if self.is_my_turn and self.pending_action == PendingAction.PLAY and pile == 'event' and self.game.check_event(ce.Cecchino) and sum((c.name == cs.Bang(0,0).name for c in self.hand)) >= 2: self.is_using_checchino = True self.available_cards = [{ 'name': p['name'], @@ -1224,7 +1224,7 @@ class Player: if isinstance(card, tvosc.RitornoDiFiamma): self.game.attack(self, self.attacker.name, card_name=card.name) self.event_type = '' - elif len([c for c in self.hand if (isinstance(c, cs.Mancato) and c.can_be_used_now) or (self.character.check(self.game, chars.CalamityJanet) and isinstance(c, cs.Bang)) or self.character.check(self.game, chd.ElenaFuente)]) == 0 and len([c for c in self.equipment if c.can_be_used_now and isinstance(c, cs.Mancato)]) == 0: + elif not any(((isinstance(c, cs.Mancato) and c.can_be_used_now) or (self.character.check(self.game, chars.CalamityJanet) and isinstance(c, cs.Bang)) or self.character.check(self.game, chd.ElenaFuente) for c in self.hand)) and not any((c.can_be_used_now and isinstance(c, cs.Mancato) for c in self.equipment)): self.on_failed_response_cb() if self.game: self.game.responders_did_respond_resume_turn(did_lose=True) diff --git a/backend/server.py b/backend/server.py index d2c90da..ee4dc7f 100644 --- a/backend/server.py +++ b/backend/server.py @@ -68,7 +68,7 @@ def bang_handler(func): def advertise_lobbies(): sio.emit('lobbies', room='lobby', data=[{'name': g.name, 'players': len(g.players), 'locked': g.password != ''} for g in games if not g.started and len(g.players) < 10 and not g.is_hidden]) sio.emit('spectate_lobbies', room='lobby', data=[{'name': g.name, 'players': len(g.players), 'locked': g.password != ''} for g in games if g.started and not g.is_hidden]) - Metrics.send_metric('lobbies', points=[len([g for g in games if not g.is_replay])]) + Metrics.send_metric('lobbies', points=[sum(not g.is_replay for g in games)]) Metrics.send_metric('online_players', points=[online_players]) @sio.event @@ -736,7 +736,7 @@ def discord_auth(sid, data): def pool_metrics(): sio.sleep(60) - Metrics.send_metric('lobbies', points=[len([g for g in games if not g.is_replay])]) + Metrics.send_metric('lobbies', points=[sum(not g.is_replay for g in games)]) Metrics.send_metric('online_players', points=[online_players]) pool_metrics() From e1fe906dbfe1643d5bc130e0e8a050bfbda7fbd9 Mon Sep 17 00:00:00 2001 From: Alberto Xamin Date: Mon, 9 Jan 2023 13:31:34 +0000 Subject: [PATCH 28/36] hurt indicator --- backend/bang/players.py | 1 + frontend/src/components/Player.vue | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/backend/bang/players.py b/backend/bang/players.py index f7e025b..86867df 100644 --- a/backend/bang/players.py +++ b/backend/bang/players.py @@ -1141,6 +1141,7 @@ class Player: def take_damage_response(self): self.lives -= 1 + self.sio.emit('hurt', room=self.sid, data=f'') if self.lives > 0: if self.character.check(self.game, chars.BartCassidy): self.sio.emit('chat_message', room=self.game.name, diff --git a/frontend/src/components/Player.vue b/frontend/src/components/Player.vue index 39bdfdb..58e8c03 100644 --- a/frontend/src/components/Player.vue +++ b/frontend/src/components/Player.vue @@ -70,6 +70,7 @@ :cards="notScrappedHand" :select="holydayScrapAdd" :cancel="() => {holydayScrap = false;scrapHand=[]}"/> +
@@ -135,6 +136,7 @@ export default { committed_suit_manette: null, gold_nuggets: 0, cantplaycard: false, + hurt: false, }), sockets: { role(role) { @@ -206,6 +208,12 @@ export default { this.notifycard = null }.bind(this), 4000) }, + hurt() { + this.hurt = true + setTimeout(function(){ + this.hurt = false + }.bind(this), 500) + }, cant_play_card() { this.cantplaycard = true setTimeout(function(){ @@ -513,6 +521,10 @@ export default { margin: 10pt 0pt; overflow:auto; } +.hurt-notify { + pointer-events: none; + animation: disappear 0.5s ease-in forwards; +} .turn-notify { pointer-events: none; animation: disappear 2s ease-in forwards; From c13b79c38bb177bea96be181a8a3d43bef6f3b8a Mon Sep 17 00:00:00 2001 From: Alberto Xamin Date: Mon, 9 Jan 2023 14:10:38 +0000 Subject: [PATCH 29/36] add tornado --- .../expansions/the_valley_of_shadows/cards.py | 10 ++++++++++ backend/bang/game.py | 16 ++++++++++++++++ backend/bang/players.py | 15 +++++++++++++++ frontend/src/i18n/en.json | 2 ++ frontend/src/i18n/it.json | 2 ++ 5 files changed, 45 insertions(+) diff --git a/backend/bang/expansions/the_valley_of_shadows/cards.py b/backend/bang/expansions/the_valley_of_shadows/cards.py index cbf76f6..1cf5ef1 100644 --- a/backend/bang/expansions/the_valley_of_shadows/cards.py +++ b/backend/bang/expansions/the_valley_of_shadows/cards.py @@ -104,6 +104,15 @@ class Tomahawk(Card): return True return False +class Tornado(Card): + def __init__(self, suit, number): + super().__init__(suit, 'Tornado', number) + self.icon = '🌪️' + + def play_card(self, player, against, _with=None): + player.game.discard_others(player, card_name=self.name) + return True + class Sventagliata(Bang): def __init__(self, suit, number): super().__init__(suit, number) @@ -217,6 +226,7 @@ def get_starting_deck() -> List[Card]: # Mira(Suit.CLUBS, 6), # Poker(Suit.HEARTS, 'J'), # tutti gli altri scartano 1 carta a scelta, se non ci sono assi allora pesca 2 dal mazzo RitornoDiFiamma(Suit.CLUBS, 'Q'), # un mancato che fa bang + Tornado(Suit.CLUBS, "A"), ] for c in cards: c.expansion_icon = '👻️' diff --git a/backend/bang/game.py b/backend/bang/game.py index be69728..d6db2e2 100644 --- a/backend/bang/game.py +++ b/backend/bang/game.py @@ -315,6 +315,22 @@ class Game: self.players[i].notify_self() self.notify_event_card() + def discard_others(self, attacker: pl.Player, card_name:str=None): + self.attack_in_progress = True + attacker.pending_action = pl.PendingAction.WAIT + attacker.notify_self() + self.waiting_for = 0 + self.ready_count = 0 + for p in self.get_alive_players(): + if len(p.hand) > 0: + if p.get_discarded(attacker=attacker, card_name=card_name): + self.waiting_for += 1 + p.notify_self() + if self.waiting_for == 0: + attacker.pending_action = pl.PendingAction.PLAY + attacker.notify_self() + self.attack_in_progress = False + def attack_others(self, attacker: pl.Player, card_name:str=None): self.attack_in_progress = True attacker.pending_action = pl.PendingAction.WAIT diff --git a/backend/bang/players.py b/backend/bang/players.py index 86867df..47da35d 100644 --- a/backend/bang/players.py +++ b/backend/bang/players.py @@ -828,6 +828,14 @@ class Player: self.sio.emit('chat_message', room=player.game.name, data=f'_play_card_against|{player.name}|Fantasma|{player.name}') self.pending_action = PendingAction.PLAY self.notify_self() + elif 'choose_tornado' in self.choose_text: + if card_index <= len(self.available_cards): + self.game.deck.scrap_pile.append(self.hand.pop(card_index)) + self.hand.append(self.game.deck.draw()) + self.hand.append(self.game.deck.draw()) + self.pending_action = PendingAction.WAIT + self.game.responders_did_respond_resume_turn() + self.notify_self() elif self.game.check_event(ceh.NuovaIdentita) and self.choose_text == 'choose_nuova_identita': if card_index == 1: # the other character self.character = self.not_chosen_character @@ -1036,6 +1044,13 @@ class Player: self.on_failed_response_cb = self.take_no_damage_response self.notify_self() + def get_discarded(self, attacker=None, card_name=None): + self.pending_action = PendingAction.CHOOSE + if card_name == 'Tornado': + self.choose_text = 'choose_tornado' + self.available_cards = self.hand + return True + def get_banged(self, attacker, double=False, no_dmg=False, card_index=None, card_name=None): self.attacker = attacker self.attacking_card = card_name diff --git a/frontend/src/i18n/en.json b/frontend/src/i18n/en.json index 95e36e7..dfb6546 100644 --- a/frontend/src/i18n/en.json +++ b/frontend/src/i18n/en.json @@ -56,6 +56,8 @@ "choose_ranch": "Choose the cards to replace", "choose_dalton": "Choose which equipment to discard", "choose_fratelli_di_sangue": "Choose who you want to donate one of your lives", + "choose_fantasma": "Choose who to bring back to life", + "choose_tornado": "Choose a card to discard for the tornado", "choose_cecchino": "Choose who to shoot", "choose_rimbalzo_player": "Choose the target of the bang", "choose_rimbalzo_card": "Choose the card to discard the bang to", diff --git a/frontend/src/i18n/it.json b/frontend/src/i18n/it.json index cd1f5fb..1c0b00e 100644 --- a/frontend/src/i18n/it.json +++ b/frontend/src/i18n/it.json @@ -56,6 +56,8 @@ "choose_ranch": "Scegli le carte da sostituire", "choose_dalton": "Scegli che equipaggiamento scartare", "choose_fratelli_di_sangue": "Scegli a chi donare una delle tue vite", + "choose_fantasma": "Scegli chi riportare in vita", + "choose_tornado": "Scegli una carta da scartare per il tornado", "choose_cecchino": "Scegli contro chi sparare", "choose_rimbalzo_player": "Scegli contro chi scartare il bang", "choose_rimbalzo_card": "Scegli contro che carta scartare il bang", From 02311e7cec2ffb69556eb6670ca78ad4dd3d2751 Mon Sep 17 00:00:00 2001 From: Alberto Xamin Date: Mon, 9 Jan 2023 15:31:56 +0000 Subject: [PATCH 30/36] add player shuffling --- backend/bang/game.py | 5 +++++ backend/server.py | 6 ++++++ frontend/src/components/Lobby.vue | 20 ++++++++++++++++++-- frontend/src/i18n/en.json | 1 + frontend/src/i18n/it.json | 1 + 5 files changed, 31 insertions(+), 2 deletions(-) diff --git a/backend/bang/game.py b/backend/bang/game.py index d6db2e2..119b75c 100644 --- a/backend/bang/game.py +++ b/backend/bang/game.py @@ -80,6 +80,11 @@ class Game: self.rpc_log = [] self.is_replay = False + def shuffle_players(self): + if not self.started: + random.shuffle(self.players) + self.notify_room() + def reset(self): for p in self.players: if (p.sid == p.name): diff --git a/backend/server.py b/backend/server.py index ee4dc7f..02b8b58 100644 --- a/backend/server.py +++ b/backend/server.py @@ -330,6 +330,12 @@ def start_game(sid): ses.game.start_game() advertise_lobbies() +@sio.event +@bang_handler +def shuffle_players(sid): + ses: Player = sio.get_session(sid) + ses.game.shuffle_players() + @sio.event @bang_handler def set_character(sid, name): diff --git a/frontend/src/components/Lobby.vue b/frontend/src/components/Lobby.vue index 98cd654..82031d8 100644 --- a/frontend/src/components/Lobby.vue +++ b/frontend/src/components/Lobby.vue @@ -70,6 +70,7 @@ 🤖 +
@@ -240,7 +241,7 @@ export default { return '' }, isRoomOwner() { - return this.players.length > 0 && this.players[0].name == this.username + return this.players.length > 0 && this.players.filter(x => !x.is_bot)[0].name == this.username }, startGameCard() { if (!this.started && this.players.length > 2 && this.isRoomOwner) { @@ -253,6 +254,16 @@ export default { } return null; }, + shufflePlayersCard() { + if (!this.started && this.players.length > 2 && this.isRoomOwner) { + return { + name: this.$t('shuffle_players'), + icon: '🔀', + is_equipment: true, + } + } + return null; + }, playersTable() { if (Vue.config.devtools) console.log('update players') @@ -302,11 +313,12 @@ export default { }, getPlayerCard(player) { let icon = '' + let owner = this.players.filter(x => !x.is_bot)[0]; if (!this.started) icon = '🤠' else icon = player.ready !== undefined ? ((player.ready)?'👍': '🤔') : (player.is_sheriff ? '⭐' : player.icon) return { name: player.name, - number: ((this.username == player.name) ? this.$t('you') : (this.players[0].name == player.name) ? this.$t('owner') :'') + (player.dist ? `${player.dist}⛰` : ''), + number: ((this.username == player.name) ? this.$t('you') : (owner.name == player.name) ? this.$t('owner') :'') + (player.dist ? `${player.dist}⛰` : ''), icon: icon, is_character: true, avatar: player.avatar, @@ -316,6 +328,10 @@ export default { this.started = true; this.$socket.emit('start_game') }, + shufflePlayers() { + this.started = true; + this.$socket.emit('shuffle_players') + }, choose(player_name) { if (Vue.config.devtools) console.log('choose from' + player_name) diff --git a/frontend/src/i18n/en.json b/frontend/src/i18n/en.json index dfb6546..c9264a1 100644 --- a/frontend/src/i18n/en.json +++ b/frontend/src/i18n/en.json @@ -9,6 +9,7 @@ "tip_7": "If you want to help us translate the game in your language, ping us on discord!", "tip_8": "If you disconnect during in an ongoing game you will be replaced by a bot (while you are gone)!", "online_players": "Online players: ", + "shuffle_players": "Shuffle Players", "choose_username": "Pick an username:", "report_bug": "Write what the bug consists of", "report": "Report a bug", diff --git a/frontend/src/i18n/it.json b/frontend/src/i18n/it.json index 1c0b00e..81ac1ca 100644 --- a/frontend/src/i18n/it.json +++ b/frontend/src/i18n/it.json @@ -9,6 +9,7 @@ "tip_7": "Se vuoi aiutarci a tradurre il gioco nella tua lingua scrivicelo su discord!", "tip_8": "Se ti disconnetti durante una partita verrai sostituito da un bot (durante la tua assenza)!", "online_players": "Giocatori online: ", + "shuffle_players": "Riordina Giocatori", "choose_username": "Scegli un username:", "report_bug":"Scrivi in cosa consiste il bug", "report":"Segnala un bug", From c5525527f419c339a22225a60992e2ef8bfb2b9f Mon Sep 17 00:00:00 2001 From: Alberto Xamin Date: Mon, 9 Jan 2023 15:37:25 +0000 Subject: [PATCH 31/36] fix admin status page color --- frontend/src/components/Lobby.vue | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/frontend/src/components/Lobby.vue b/frontend/src/components/Lobby.vue index 82031d8..e5b7dd5 100644 --- a/frontend/src/components/Lobby.vue +++ b/frontend/src/components/Lobby.vue @@ -87,7 +87,7 @@ -
+
@@ -456,6 +456,9 @@ export default { justify-content: space-evenly; margin-bottom: 12pt; } +#admin-status { + position:absolute;width:100%;height:100%;overflow:auto;background:var(--bg-color); opacity: 0.8; +} #turn-indicator{ position: absolute; width: 100%; From 33bc725eea6169b4a65ccd4269da16e177ef61ce Mon Sep 17 00:00:00 2001 From: Alberto Xamin Date: Mon, 9 Jan 2023 16:02:31 +0000 Subject: [PATCH 32/36] add bandidos --- .../expansions/the_valley_of_shadows/cards.py | 6 ++---- backend/bang/game.py | 2 +- backend/bang/players.py | 16 +++++++++++++++- frontend/src/i18n/en.json | 1 + frontend/src/i18n/it.json | 1 + 5 files changed, 20 insertions(+), 6 deletions(-) diff --git a/backend/bang/expansions/the_valley_of_shadows/cards.py b/backend/bang/expansions/the_valley_of_shadows/cards.py index 1cf5ef1..b1549b9 100644 --- a/backend/bang/expansions/the_valley_of_shadows/cards.py +++ b/backend/bang/expansions/the_valley_of_shadows/cards.py @@ -167,9 +167,7 @@ class Bandidos(Card): self.alt_text = "👤🃏🃏/💔" def play_card(self, player, against, _with=None): - #TODO - # super().play_card(player, against=against) - # player.game.attack(player, against) + player.game.discard_others(player, card_name=self.name) return True class Fuga(Card): @@ -221,7 +219,7 @@ def get_starting_deck() -> List[Card]: Tomahawk(Suit.DIAMONDS, 'A'), # Sventagliata(Suit.SPADES, 2), # Salvo(Suit.HEARTS, 5), - # Bandidos(Suit.DIAMONDS,'Q'), # gli altri giocatori scelgono se scartare 2 carte o perdere 1 punto vita + Bandidos(Suit.DIAMONDS,'Q'), # gli altri giocatori scelgono se scartare 2 carte o perdere 1 punto vita # Fuga(Suit.HEARTS, 3), # evita l'effetto di carte marroni (tipo panico cat balou) di cui sei bersaglio # Mira(Suit.CLUBS, 6), # Poker(Suit.HEARTS, 'J'), # tutti gli altri scartano 1 carta a scelta, se non ci sono assi allora pesca 2 dal mazzo diff --git a/backend/bang/game.py b/backend/bang/game.py index 119b75c..366e325 100644 --- a/backend/bang/game.py +++ b/backend/bang/game.py @@ -327,7 +327,7 @@ class Game: self.waiting_for = 0 self.ready_count = 0 for p in self.get_alive_players(): - if len(p.hand) > 0: + if len(p.hand) > 0 and (p != attacker or card_name == 'Tornado'): if p.get_discarded(attacker=attacker, card_name=card_name): self.waiting_for += 1 p.notify_self() diff --git a/backend/bang/players.py b/backend/bang/players.py index 47da35d..d520a27 100644 --- a/backend/bang/players.py +++ b/backend/bang/players.py @@ -836,6 +836,16 @@ class Player: self.pending_action = PendingAction.WAIT self.game.responders_did_respond_resume_turn() self.notify_self() + elif 'choose_bandidos' in self.choose_text: + if card_index <= len(self.available_cards): + self.game.deck.scrap_pile.append(self.hand.pop(card_index)) + self.mancato_needed -= 1 + else: + self.lives -= 1 + if self.mancato_needed <= 0: + self.pending_action = PendingAction.WAIT + self.game.responders_did_respond_resume_turn() + self.notify_self() elif self.game.check_event(ceh.NuovaIdentita) and self.choose_text == 'choose_nuova_identita': if card_index == 1: # the other character self.character = self.not_chosen_character @@ -1046,9 +1056,13 @@ class Player: def get_discarded(self, attacker=None, card_name=None): self.pending_action = PendingAction.CHOOSE + self.available_cards = self.hand.copy() if card_name == 'Tornado': self.choose_text = 'choose_tornado' - self.available_cards = self.hand + if card_name == 'Bandidos': + self.choose_text = 'choose_bandidos' + self.mancato_needed = min(2, len(self.hand)) + self.available_cards.append({'name': '-1hp', 'icon': '💔', 'noDesc': True}) return True def get_banged(self, attacker, double=False, no_dmg=False, card_index=None, card_name=None): diff --git a/frontend/src/i18n/en.json b/frontend/src/i18n/en.json index c9264a1..2ea8e73 100644 --- a/frontend/src/i18n/en.json +++ b/frontend/src/i18n/en.json @@ -59,6 +59,7 @@ "choose_fratelli_di_sangue": "Choose who you want to donate one of your lives", "choose_fantasma": "Choose who to bring back to life", "choose_tornado": "Choose a card to discard for the tornado", + "choose_bandidos": "Choose between discarding 2 cards or losing a life (1 card if you only have 1)", "choose_cecchino": "Choose who to shoot", "choose_rimbalzo_player": "Choose the target of the bang", "choose_rimbalzo_card": "Choose the card to discard the bang to", diff --git a/frontend/src/i18n/it.json b/frontend/src/i18n/it.json index 81ac1ca..a5eaddf 100644 --- a/frontend/src/i18n/it.json +++ b/frontend/src/i18n/it.json @@ -59,6 +59,7 @@ "choose_fratelli_di_sangue": "Scegli a chi donare una delle tue vite", "choose_fantasma": "Scegli chi riportare in vita", "choose_tornado": "Scegli una carta da scartare per il tornado", + "choose_bandidos": "Scegli tra scartare 2 carte o perdere una vita (1 carta se ne hai solo 1)", "choose_cecchino": "Scegli contro chi sparare", "choose_rimbalzo_player": "Scegli contro chi scartare il bang", "choose_rimbalzo_card": "Scegli contro che carta scartare il bang", From 888725a6ecf83dba5c940beafc95ca7467325ba2 Mon Sep 17 00:00:00 2001 From: Alberto Xamin Date: Mon, 9 Jan 2023 17:45:50 +0100 Subject: [PATCH 33/36] Update players.py --- backend/bang/players.py | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/bang/players.py b/backend/bang/players.py index d520a27..04fbea2 100644 --- a/backend/bang/players.py +++ b/backend/bang/players.py @@ -838,6 +838,7 @@ class Player: self.notify_self() elif 'choose_bandidos' in self.choose_text: if card_index <= len(self.available_cards): + self.available_cards.pop(card_index)) self.game.deck.scrap_pile.append(self.hand.pop(card_index)) self.mancato_needed -= 1 else: From a85b42d5b577b7d093dd9a913682f8e12badf16d Mon Sep 17 00:00:00 2001 From: Alberto Xamin Date: Mon, 9 Jan 2023 18:09:23 +0100 Subject: [PATCH 34/36] fix bugs --- backend/bang/players.py | 4 ++-- frontend/src/i18n/en.json | 3 ++- frontend/src/i18n/it.json | 3 ++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/backend/bang/players.py b/backend/bang/players.py index 04fbea2..477b277 100644 --- a/backend/bang/players.py +++ b/backend/bang/players.py @@ -731,7 +731,7 @@ class Player: target = self.game.get_player_named(self.target_p) card = None if (target.name == self.name): - card = self.equipment.pop(card_index) + card = self.equipment.pop(card_index if card_index < len(target.hand) else card_index - len(target.hand)) elif card_index >= len(target.hand): card = target.equipment.pop(card_index - len(target.hand)) else: @@ -838,7 +838,7 @@ class Player: self.notify_self() elif 'choose_bandidos' in self.choose_text: if card_index <= len(self.available_cards): - self.available_cards.pop(card_index)) + self.available_cards.pop(card_index) self.game.deck.scrap_pile.append(self.hand.pop(card_index)) self.mancato_needed -= 1 else: diff --git a/frontend/src/i18n/en.json b/frontend/src/i18n/en.json index 2ea8e73..5037eea 100644 --- a/frontend/src/i18n/en.json +++ b/frontend/src/i18n/en.json @@ -138,7 +138,8 @@ "gold_rush_pay_discard": "{0} discarded {2} from {1}.", "choose_emporio": "{0} has chosen {1} from General Store.", "shotgun_scrap": "When the shotgun hit {0} a card flew away from his hand ({1})", - "taglia_reward": "{1} got a card from the bounty on {0}" + "taglia_reward": "{1} got a card from the bounty on {0}", + "snake_bit": "{0} was bitten by the Rattle Snake." }, "foc": { "leggedelwest": "He must play this card on this turn if possible." diff --git a/frontend/src/i18n/it.json b/frontend/src/i18n/it.json index a5eaddf..b72f373 100644 --- a/frontend/src/i18n/it.json +++ b/frontend/src/i18n/it.json @@ -138,7 +138,8 @@ "gold_rush_pay_discard": "{0} ha fatto scartare {2} a {1}.", "choose_emporio": "{0} ha scelto {1} da Emporio.", "shotgun_scrap": "Quando lo shotgun ha colpito {0} gli ha tolto una carta ({1})", - "taglia_reward": "{1} ha ottenuto ricompensa dalla taglia su {0}" + "taglia_reward": "{1} ha ottenuto ricompensa dalla taglia su {0}", + "snake_bit": "{0} è stato morso dal Serpente a Sonagli." }, "foc": { "leggedelwest": "Ed è obbligato a usarla nel suo turno, se possibile" From feedc5c784701020ff72d3585558e7ae4dfe1ddc Mon Sep 17 00:00:00 2001 From: Alberto Xamin Date: Mon, 9 Jan 2023 17:40:43 +0000 Subject: [PATCH 35/36] fix bots --- backend/bang/game.py | 1 + backend/bang/players.py | 6 ++++-- backend/server.py | 4 ++++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/backend/bang/game.py b/backend/bang/game.py index 366e325..9cdcc13 100644 --- a/backend/bang/game.py +++ b/backend/bang/game.py @@ -37,6 +37,7 @@ debug_commands = [ {'cmd':'/meinfo', 'help':'Get player data'}, {'cmd':'/gameinfo', 'help':'Get game data'}, {'cmd':'/playerinfo', 'help':'Get player data - sample /playerinfo player'}, + {'cmd':'/cardinfo', 'help':'Get card data - sample /cardinfo handindex'}, {'cmd':'/mebot', 'help':'Toggles bot mode'}, {'cmd':'/getnuggets', 'help':'Adds nuggets to yourself - sample /getnuggets 5'}, {'cmd':'/startwithseed', 'help':'start the game with custom seed'}, diff --git a/backend/bang/players.py b/backend/bang/players.py index 477b277..641892f 100644 --- a/backend/bang/players.py +++ b/backend/bang/players.py @@ -303,7 +303,7 @@ class Player: self.draw('') elif self.pending_action == PendingAction.PLAY: non_blocked_cards = [card for card in self.hand if (not self.game.check_event(ceh.Manette) or card.suit == self.committed_suit_manette)] - equippables = [c for c in non_blocked_cards if (c.is_equipment or c.usable_next_turn) and not isinstance(c, cs.Prigione) and not any((type(c) == type(x) and not (c.is_weapon and c.must_be_used) for x in self.equipment))] + equippables = [c for c in non_blocked_cards if (c.is_equipment or c.usable_next_turn) and not isinstance(c, cs.Prigione) and not c.need_target and not any((type(c) == type(x) and not (c.is_weapon and c.must_be_used) for x in self.equipment))] misc = [c for c in non_blocked_cards if not c.need_target and (isinstance(c, cs.WellsFargo) or isinstance(c, cs.Indiani) or isinstance(c, cs.Gatling) or isinstance(c, cs.Diligenza) or isinstance(c, cs.Emporio) or ((isinstance(c, cs.Birra) and self.lives < self.max_lives or c.must_be_used) and not self.game.check_event(ceh.IlReverendo)) or (c.need_with and len(self.hand) > 1 and not (isinstance(c, csd.Whisky) and self.lives == self.max_lives))) and not (not c.can_be_used_now and self.game.check_event(ce.IlGiudice)) and not c.is_equipment] need_target = [c for c in non_blocked_cards if c.need_target and c.can_be_used_now and not (c.need_with and len(self.hand) < 2) and not (type(c) == type(cs.Bang) and (self.game.check_event(ceh.Sermone) or (self.has_played_bang and (not any((isinstance(c, cs.Volcanic) for c in self.equipment)) or self.game.check_event(ce.Lazo))))) and not (isinstance(c, cs.Prigione) and self.game.check_event(ce.IlGiudice)) or isinstance(c, cs.Duello) or isinstance(c, cs.CatBalou) or isinstance(c, csd.Pugno)] @@ -323,6 +323,8 @@ class Player: return if len(equippables) > 0 and not self.game.check_event(ce.IlGiudice): for c in equippables: + if isinstance(c, tvosc.Fantasma) and len(self.game.get_dead_players(include_ghosts=False)) == 0: + continue if self.play_card(self.hand.index(c)): return elif len(misc) > 0: @@ -1259,7 +1261,7 @@ class Player: self.on_failed_response_cb() if self.game: self.game.responders_did_respond_resume_turn(did_lose=True) - if isinstance(card, tvosc.RitornoDiFiamma): + if isinstance(card, tvosc.RitornoDiFiamma) and self.attacker: self.game.attack(self, self.attacker.name, card_name=card.name) else: self.pending_action = PendingAction.RESPOND diff --git a/backend/server.py b/backend/server.py index 02b8b58..23c023e 100644 --- a/backend/server.py +++ b/backend/server.py @@ -639,6 +639,10 @@ def chat_message(sid, msg, pl=None): cmd = msg.split() if len(cmd) == 2: sio.emit('chat_message', room=sid, data={'color': f'', 'text':json.dumps(ses.game.get_player_named(cmd[1]).__dict__, default=lambda o: f'<{o.__class__.__name__}() not serializable>'), 'type': 'json'}) + elif '/cardinfo' in msg: + cmd = msg.split() + if len(cmd) == 2: + sio.emit('chat_message', room=sid, data={'color': f'', 'text':json.dumps(ses.hand[int(cmd[1])].__dict__, default=lambda o: f'<{o.__class__.__name__}() not serializable>'), 'type': 'json'}) elif '/mebot' in msg: ses.is_bot = not ses.is_bot if (ses.is_bot): From 8734c01843e1ef4a57e01c064dd8719d9accce31 Mon Sep 17 00:00:00 2001 From: Alberto Xamin Date: Mon, 9 Jan 2023 18:00:28 +0000 Subject: [PATCH 36/36] improve character visual --- backend/bang/characters.py | 1 + backend/server.py | 3 ++- frontend/src/components/Card.vue | 2 +- frontend/src/components/Chooser.vue | 2 -- frontend/src/components/Lobby.vue | 8 +++++++- 5 files changed, 11 insertions(+), 5 deletions(-) diff --git a/backend/bang/characters.py b/backend/bang/characters.py index e327a28..460f996 100644 --- a/backend/bang/characters.py +++ b/backend/bang/characters.py @@ -9,6 +9,7 @@ class Character(ABC): self.max_lives = max_lives self.sight_mod = sight_mod self.visibility_mod = visibility_mod + self.is_character = True self.pick_mod = pick_mod self.desc = desc self.icon = '🤷‍♂️' diff --git a/backend/server.py b/backend/server.py index 23c023e..970d959 100644 --- a/backend/server.py +++ b/backend/server.py @@ -208,7 +208,8 @@ def disconnect(sid): sio.emit('players', room='lobby', data=online_players) if sio.get_session(sid).game and sio.get_session(sid).disconnect(): sio.close_room(sio.get_session(sid).game.name) - games.pop(games.index(sio.get_session(sid).game)) + if sio.get_session(sid).game in games: + games.pop(games.index(sio.get_session(sid).game)) print('disconnect ', sid) advertise_lobbies() Metrics.send_metric('online_players', points=[online_players]) diff --git a/frontend/src/components/Card.vue b/frontend/src/components/Card.vue index f1ef573..552c035 100644 --- a/frontend/src/components/Card.vue +++ b/frontend/src/components/Card.vue @@ -177,7 +177,7 @@ export default { left:3pt; } .card.character .suit { - font-size: x-small; + font-size: small; right: 3pt; text-align: center; } diff --git a/frontend/src/components/Chooser.vue b/frontend/src/components/Chooser.vue index 785144c..27dc68c 100644 --- a/frontend/src/components/Chooser.vue +++ b/frontend/src/components/Chooser.vue @@ -56,8 +56,6 @@ export default { //console.log(card) if (card.noDesc || card.name == null || card.name == "PewPew!") this.desc = "" - else if (card.is_character) - this.desc = card.name else if (card.goal) this.desc = this.$t(`cards.${card.name}.name`) else if (card.desc) diff --git a/frontend/src/components/Lobby.vue b/frontend/src/components/Lobby.vue index e5b7dd5..f29a790 100644 --- a/frontend/src/components/Lobby.vue +++ b/frontend/src/components/Lobby.vue @@ -42,7 +42,7 @@
-
+
💵️ @@ -504,5 +504,11 @@ background-position-x: 80px; min-width: 25vw; max-width: 25vw; } + .player-in-table { + transition: all 0.2s ease-in-out; + } + .player-in-table:hover { + transform: translateY(-5px) scale(1.05); + } }