From 88d0ba649685a0ef6c3bb24079e4380b5a955576 Mon Sep 17 00:00:00 2001 From: HF Date: Mon, 3 Oct 2022 21:32:19 +0200 Subject: [PATCH] refactor pixel update socket client update translation templates fix #16 --- i18n/template-ssr.pot | 440 ++++++++-------- i18n/template.pot | 637 +++++++++++++---------- src/client.js | 27 +- src/components/GlobalCaptcha.jsx | 1 - src/controls/PixelPainterControls.js | 8 +- src/socket/SocketClient.js | 41 +- src/store/actions/index.js | 22 - src/store/actions/socket.js | 30 +- src/store/middleware/audio.js | 2 +- src/store/middleware/rendererHook.js | 2 +- src/store/middleware/socketClientHook.js | 8 - src/store/reducers/fetching.js | 9 + src/store/reducers/ranks.js | 2 +- src/store/reducers/user.js | 18 +- src/ui/PixelTransferController.js | 269 ++++++++++ src/ui/Renderer2D.js | 8 +- src/ui/Renderer3D.js | 27 +- src/ui/placePixel.js | 277 ---------- 18 files changed, 927 insertions(+), 901 deletions(-) create mode 100644 src/ui/PixelTransferController.js delete mode 100644 src/ui/placePixel.js diff --git a/i18n/template-ssr.pot b/i18n/template-ssr.pot index 54b5f08..c038d33 100644 --- a/i18n/template-ssr.pot +++ b/i18n/template-ssr.pot @@ -3,244 +3,116 @@ msgstr "" "Content-Type: text/plain; charset=utf-8\n" "Plural-Forms: nplurals=2; plural=(n!=1);\n" -#: src/core/ChatProvider.js:390 +#: src/core/ChatProvider.js:434 msgid "You can not send chat messages with proxy" msgstr "" -#: src/core/ChatProvider.js:392 -msgid "You are banned" +#: src/core/ChatProvider.js:436 +msgid "Your country is temporary muted from this chat channel" msgstr "" -#: src/core/ChatProvider.js:394 -msgid "Your Internet Provider is banned" -msgstr "" - -#: src/core/ChatProvider.js:396 -msgid "You are not allowed to use chat" -msgstr "" - -#: src/core/ChatProvider.js:411 -#, javascript-format -msgid "You are sending messages too fast, you have to wait ${ waitTime }s :(" -msgstr "" - -#: src/core/ChatProvider.js:415 -msgid "You don't have access to this channel" -msgstr "" - -#: src/core/ChatProvider.js:433 -msgid "Your mail has to be verified in order to chat" -msgstr "" - -#: src/core/ChatProvider.js:438 +#: src/core/ChatProvider.js:439 msgid "You are permanently muted, join our guilded to apppeal the mute" msgstr "" +#: src/core/ChatProvider.js:441 +msgid "You are banned" +msgstr "" + #: src/core/ChatProvider.js:443 +msgid "Your Internet Provider is banned" +msgstr "" + +#: src/core/ChatProvider.js:448 #, javascript-format msgid "You are muted for another ${ timeMin } minutes" msgstr "" -#: src/core/ChatProvider.js:445 -msgid "You are muted for another ${ muted } seconds" +#: src/core/ChatProvider.js:450 +msgid "You are muted for another ${ ttl } seconds" msgstr "" -#: src/core/ChatProvider.js:453 -msgid "Ow no! Spam protection decided to mute you" +#: src/core/ChatProvider.js:467 +#, javascript-format +msgid "You are sending messages too fast, you have to wait ${ waitTime }s :(" msgstr "" -#: src/core/ChatProvider.js:464 +#: src/core/ChatProvider.js:471 +msgid "You don't have access to this channel" +msgstr "" + +#: src/core/ChatProvider.js:488 +msgid "Your mail has to be verified in order to chat" +msgstr "" + +#: src/core/ChatProvider.js:498 msgid "You can't send a message this long :(" msgstr "" -#: src/core/ChatProvider.js:468 +#: src/core/ChatProvider.js:502 msgid "Please use int channel" msgstr "" -#: src/core/ChatProvider.js:475 -msgid "Your country is temporary muted from this chat channel" -msgstr "" - -#: src/core/ChatProvider.js:483 +#: src/core/ChatProvider.js:510 msgid "Stop flooding." msgstr "" -#: src/routes/reset_password.js:37 +#: src/routes/reset_password.js:39 msgid "You sent an empty password or invalid data :(" msgstr "" -#: src/routes/reset_password.js:49 +#: src/routes/reset_password.js:51 msgid "This password-reset link isn't valid anymore :(" msgstr "" -#: src/routes/reset_password.js:60 +#: src/routes/reset_password.js:62 msgid "Your passwords do not match :(" msgstr "" -#: src/routes/reset_password.js:75 +#: src/routes/reset_password.js:77 msgid "User doesn't exist in our database :(" msgstr "" -#: src/routes/reset_password.js:87 +#: src/routes/reset_password.js:89 msgid "Passowrd successfully changed." msgstr "" -#: src/routes/reset_password.js:106 +#: src/routes/reset_password.js:108 msgid "Invalid url :( Please check your mail again." msgstr "" -#: src/routes/reset_password.js:119 -msgid "" -"This passwort reset link is wrong or already expired, please request a new " -"one (Note: you can use those links just once)" +#: src/ssr/PopUp.jsx:58 +msgid "ppfun" msgstr "" -#: src/ssr/Globe.jsx:33 -msgid "PixelPlanet.Fun 3DGlobe" -msgstr "" - -#: src/ssr/Globe.jsx:34 -msgid "A 3D globe of our whole map" -msgstr "" - -#: src/ssr/Globe.jsx:47 -msgid "Double click on globe to go back." -msgstr "" - -#: src/ssr/Globe.jsx:48 -msgid "Loading..." -msgstr "" - -#: src/ssr/Win.jsx:55 -#: src/ssr/Win.jsx:56 +#: src/ssr/PopUp.jsx:59 msgid "PixelPlanet.Fun PopUp" msgstr "" -#: src/ssr/Main.jsx:54 +#: src/ssr/Globe.jsx:32 +msgid "PixelPlanet.Fun 3DGlobe" +msgstr "" + +#: src/ssr/Globe.jsx:33 +msgid "A 3D globe of our whole map" +msgstr "" + +#: src/ssr/Globe.jsx:46 +msgid "Double click on globe to go back." +msgstr "" + +#: src/ssr/Globe.jsx:47 +msgid "Loading..." +msgstr "" + +#: src/ssr/Main.jsx:59 msgid "PixelPlanet.Fun" msgstr "" -#: src/ssr/Main.jsx:55 +#: src/ssr/Main.jsx:60 msgid "Place color pixels on an map styled canvas with other players online" msgstr "" -#: src/core/mail.js:71 -#, javascript-format -msgid "" -"We already sent you a verification mail, you can request another one in ${ " -"minLeft } minutes." -msgstr "" - -#: src/core/mail.js:78 -msgid "Welcome ${ name } to PixelPlanet, plese verify your mail" -msgstr "" - -#: src/core/mail.js:79 -#, javascript-format -msgid "Hello ${ name }" -msgstr "" - -#: src/core/mail.js:80 -msgid "" -"welcome to our little community of pixelplacers, to use your account, you " -"have to verify your mail. You can do that here: " -msgstr "" - -#: src/core/mail.js:80 -msgid "Click to Verify" -msgstr "" - -#: src/core/mail.js:80 -#: src/core/mail.js:127 -msgid "Or by copying following url:" -msgstr "" - -#: src/core/mail.js:81 -msgid "Have fun and don't hesitate to contact us if you encouter any problems :)" -msgstr "" - -#: src/core/mail.js:82 -#: src/core/mail.js:129 -msgid "Thanks" -msgstr "" - -#: src/core/mail.js:92 -msgid "Mail is not configured on the server" -msgstr "" - -#: src/core/mail.js:101 -msgid "" -"We already sent you a mail with instructions. Please wait before requesting " -"another mail." -msgstr "" - -#: src/core/mail.js:109 -msgid "Couldn't find this mail in our database" -msgstr "" - -#: src/core/mail.js:125 -msgid "You forgot your password for PixelPlanet? Get a new one here" -msgstr "" - -#: src/core/mail.js:126 -msgid "Hello" -msgstr "" - -#: src/core/mail.js:127 -msgid "" -"You requested to get a new password. You can change your password within " -"the next 30min here: " -msgstr "" - -#: src/core/mail.js:127 -#: src/ssr/PasswordReset.jsx:28 -#: src/ssr/PasswordReset.jsx:49 -msgid "Reset Password" -msgstr "" - -#: src/core/mail.js:128 -#, javascript-format -msgid "" -"If you did not request this mail, please just ignore it (the ip that " -"requested this mail was ${ ip })." -msgstr "" - -#: src/ssr/PasswordReset.jsx:20 -#: src/ssr/PasswordReset.jsx:40 -msgid "PixelPlanet.fun Password Reset" -msgstr "" - -#: src/ssr/PasswordReset.jsx:21 -#: src/ssr/PasswordReset.jsx:41 -msgid "Reset your password here" -msgstr "" - -#: src/ssr/PasswordReset.jsx:30 -#: src/ssr/RedirectionPage.jsx:12 -msgid "Click here" -msgstr "" - -#: src/ssr/PasswordReset.jsx:30 -msgid "to go back to pixelplanet" -msgstr "" - -#: src/ssr/PasswordReset.jsx:50 -#, javascript-format -msgid "Hello ${ name }, you can set your new password here:" -msgstr "" - -#: src/ssr/PasswordReset.jsx:54 -msgid "New Password" -msgstr "" - -#: src/ssr/PasswordReset.jsx:60 -msgid "Confirm New Password" -msgstr "" - -#: src/ssr/PasswordReset.jsx:64 -msgid "Submit" -msgstr "" - #: src/utils/validation.js:17 msgid "Email can't be empty." msgstr "" @@ -289,30 +161,72 @@ msgstr "" msgid "Password must be shorter than 60 characters." msgstr "" -#: src/routes/api/captcha.js:20 -msgid "No captcha text given" +#: src/ssr/PasswordReset.jsx:20 +#: src/ssr/PasswordReset.jsx:40 +msgid "PixelPlanet.fun Password Reset" msgstr "" -#: src/routes/api/captcha.js:25 -msgid "No captcha id given" +#: src/ssr/PasswordReset.jsx:21 +#: src/ssr/PasswordReset.jsx:41 +msgid "Reset your password here" msgstr "" -#: src/routes/api/auth/register.js:54 -#: src/routes/api/captcha.js:44 +#: src/core/MailProvider.js:105 +#: src/ssr/PasswordReset.jsx:28 +#: src/ssr/PasswordReset.jsx:49 +msgid "Reset Password" +msgstr "" + +#: src/ssr/PasswordReset.jsx:30 +#: src/ssr/RedirectionPage.jsx:12 +msgid "Click here" +msgstr "" + +#: src/ssr/PasswordReset.jsx:30 +msgid "to go back to pixelplanet" +msgstr "" + +#: src/ssr/PasswordReset.jsx:50 +#, javascript-format +msgid "Hello ${ name }, you can set your new password here:" +msgstr "" + +#: src/ssr/PasswordReset.jsx:54 +msgid "New Password" +msgstr "" + +#: src/ssr/PasswordReset.jsx:60 +msgid "Confirm New Password" +msgstr "" + +#: src/ssr/PasswordReset.jsx:65 +msgid "Submit" +msgstr "" + +#: src/routes/api/auth/register.js:59 +#: src/routes/api/captcha.js:34 msgid "You took too long, try again." msgstr "" -#: src/routes/api/auth/register.js:57 -#: src/routes/api/captcha.js:50 +#: src/routes/api/auth/register.js:62 +#: src/routes/api/captcha.js:39 msgid "You failed your captcha" msgstr "" -#: src/routes/api/auth/register.js:60 -#: src/routes/api/captcha.js:56 +#: src/routes/api/captcha.js:43 +msgid "No captcha text given" +msgstr "" + +#: src/routes/api/captcha.js:47 +msgid "No captcha id given" +msgstr "" + +#: src/routes/api/auth/register.js:65 +#: src/routes/api/captcha.js:51 msgid "Unknown Captcha Error" msgstr "" -#: src/routes/api/captcha.js:63 +#: src/routes/api/captcha.js:57 msgid "Server error occured" msgstr "" @@ -328,66 +242,71 @@ msgstr "" msgid "Just admins can do that" msgstr "" -#: src/routes/api/baninfo.js:24 +#: src/routes/api/baninfo.js:32 msgid "You are not banned" msgstr "" -#: src/routes/api/auth/verify.js:22 -#: src/routes/api/auth/verify.js:29 -msgid "Mail verification" -msgstr "" - -#: src/routes/api/auth/verify.js:23 -msgid "You are now verified :)" -msgstr "" - -#: src/routes/api/auth/verify.js:29 -msgid "" -"Your mail verification code is invalid or already expired :(, please " -"request a new one." -msgstr "" - #: src/routes/api/auth/logout.js:11 msgid "You are not even logged in." msgstr "" -#: src/routes/api/auth/delete_account.js:54 +#: src/routes/api/auth/delete_account.js:55 #: src/routes/api/auth/logout.js:20 msgid "Server error when logging out." msgstr "" -#: src/routes/api/auth/change_mail.js:38 +#: src/routes/api/auth/change_mail.js:43 #: src/routes/api/auth/change_passwd.js:34 -#: src/routes/api/auth/delete_account.js:34 +#: src/routes/api/auth/delete_account.js:35 msgid "You are not authenticated." msgstr "" -#: src/routes/api/auth/change_mail.js:47 +#: src/routes/api/auth/change_mail.js:52 #: src/routes/api/auth/change_passwd.js:43 -#: src/routes/api/auth/delete_account.js:44 +#: src/routes/api/auth/delete_account.js:45 msgid "Incorrect password!" msgstr "" -#: src/routes/api/auth/register.js:26 -msgid "No Captcha given" -msgstr "" - -#: src/routes/api/auth/register.js:29 -msgid "E-Mail already in use." +#: src/routes/api/auth/change_mail.js:21 +#: src/routes/api/auth/register.js:24 +msgid "This email provider is not allowed" msgstr "" #: src/routes/api/auth/register.js:31 +msgid "No Captcha given" +msgstr "" + +#: src/routes/api/auth/register.js:34 +msgid "E-Mail already in use." +msgstr "" + +#: src/routes/api/auth/register.js:36 msgid "Username already in use." msgstr "" -#: src/routes/api/auth/register.js:84 +#: src/routes/api/auth/register.js:89 msgid "Failed to create new user :(" msgstr "" -#: src/routes/api/auth/register.js:100 +#: src/routes/api/auth/register.js:105 msgid "Failed to establish session after register :(" msgstr "" +#: src/routes/api/auth/verify.js:26 +#: src/routes/api/auth/verify.js:35 +msgid "Mail verification" +msgstr "" + +#: src/routes/api/auth/verify.js:27 +msgid "You are now verified :)" +msgstr "" + +#: src/routes/api/auth/verify.js:35 +msgid "" +"Your mail verification code is invalid or already expired :(, please " +"request a new one." +msgstr "" + #: src/ssr/RedirectionPage.jsx:19 msgid "PixelPlanet.fun Accounts" msgstr "" @@ -467,4 +386,79 @@ msgstr "" msgid "" "A canvas for the most active players from the the previous day. Daily " "ranking updates at 00:00 UTC." +msgstr "" + +#: src/core/MailProvider.js:66 +#, javascript-format +msgid "Welcome ${ name } to PixelPlanet, plese verify your mail" +msgstr "" + +#: src/core/MailProvider.js:67 +msgid "Hello ${ name }" +msgstr "" + +#: src/core/MailProvider.js:68 +msgid "" +"welcome to our little community of pixelplacers, to use your account, you " +"have to verify your mail. You can do that here: " +msgstr "" + +#: src/core/MailProvider.js:68 +msgid "Click to Verify" +msgstr "" + +#: src/core/MailProvider.js:68 +#: src/core/MailProvider.js:105 +msgid "Or by copying following url:" +msgstr "" + +#: src/core/MailProvider.js:69 +msgid "Have fun and don't hesitate to contact us if you encouter any problems :)" +msgstr "" + +#: src/core/MailProvider.js:70 +#: src/core/MailProvider.js:107 +msgid "Thanks" +msgstr "" + +#: src/core/MailProvider.js:87 +#, javascript-format +msgid "" +"We already sent you a verification mail, you can request another one in ${ " +"minLeft } minutes." +msgstr "" + +#: src/core/MailProvider.js:103 +msgid "You forgot your password for PixelPlanet? Get a new one here" +msgstr "" + +#: src/core/MailProvider.js:104 +msgid "Hello" +msgstr "" + +#: src/core/MailProvider.js:105 +msgid "" +"You requested to get a new password. You can change your password within " +"the next 30min here: " +msgstr "" + +#: src/core/MailProvider.js:106 +#, javascript-format +msgid "" +"If you did not request this mail, please just ignore it (the ip that " +"requested this mail was ${ ip })." +msgstr "" + +#: src/core/MailProvider.js:114 +msgid "Mail is not configured on the server" +msgstr "" + +#: src/core/MailProvider.js:122 +msgid "" +"We already sent you a mail with instructions. Please wait before requesting " +"another mail." +msgstr "" + +#: src/core/MailProvider.js:130 +msgid "Couldn't find this mail in our database" msgstr "" \ No newline at end of file diff --git a/i18n/template.pot b/i18n/template.pot index b4296e8..96c4073 100644 --- a/i18n/template.pot +++ b/i18n/template.pot @@ -3,160 +3,170 @@ msgstr "" "Content-Type: text/plain; charset=utf-8\n" "Plural-Forms: nplurals=2; plural=(n!=1);\n" -#: src/controls/keypress.js:42 +#: src/controls/keypress.js:41 #, javascript-format msgid "Switched to ${ canvasName }" msgstr "" -#: src/controls/keypress.js:65 +#: src/controls/keypress.js:64 msgid "Grid ON" msgstr "" -#: src/controls/keypress.js:66 +#: src/controls/keypress.js:65 msgid "Grid OFF" msgstr "" -#: src/controls/keypress.js:76 +#: src/controls/keypress.js:75 msgid "Pixel Notify ON" msgstr "" -#: src/controls/keypress.js:77 +#: src/controls/keypress.js:76 msgid "Pixel Notify OFF" msgstr "" -#: src/controls/keypress.js:82 +#: src/controls/keypress.js:81 msgid "Muted Sound" msgstr "" -#: src/controls/keypress.js:83 +#: src/controls/keypress.js:82 msgid "Unmuted Sound" msgstr "" #: src/components/CoordinatesBox.jsx:28 #: src/components/GetIID.jsx:51 -#: src/controls/keypress.js:89 +#: src/controls/keypress.js:88 msgid "Copied!" msgstr "" -#: src/controls/keypress.js:95 +#: src/controls/keypress.js:94 msgid "Show Hidden Canvases" msgstr "" -#: src/controls/keypress.js:96 +#: src/controls/keypress.js:95 msgid "Hide Hidden Canvases" msgstr "" -#: src/ui/placePixel.js:54 +#: src/ui/PixelTransferController.js:63 msgid "Error :(" msgstr "" -#: src/ui/placePixel.js:55 +#: src/ui/PixelTransferController.js:64 msgid "Didn't get an answer from pixelplanet. Maybe try to refresh?" msgstr "" -#: src/ui/placePixel.js:202 +#: src/ui/PixelTransferController.js:96 msgid "Invalid Canvas" msgstr "" -#: src/ui/placePixel.js:203 +#: src/ui/PixelTransferController.js:97 msgid "This canvas doesn't exist" msgstr "" -#: src/ui/placePixel.js:206 -#: src/ui/placePixel.js:210 -#: src/ui/placePixel.js:214 +#: src/ui/PixelTransferController.js:100 +#: src/ui/PixelTransferController.js:104 +#: src/ui/PixelTransferController.js:108 msgid "Invalid Coordinates" msgstr "" -#: src/ui/placePixel.js:207 +#: src/ui/PixelTransferController.js:101 msgid "x out of bounds" msgstr "" -#: src/ui/placePixel.js:211 +#: src/ui/PixelTransferController.js:105 msgid "y out of bounds" msgstr "" -#: src/ui/placePixel.js:215 +#: src/ui/PixelTransferController.js:109 msgid "z out of bounds" msgstr "" -#: src/ui/placePixel.js:218 +#: src/ui/PixelTransferController.js:112 msgid "Wrong Color" msgstr "" -#: src/ui/placePixel.js:219 +#: src/ui/PixelTransferController.js:113 msgid "Invalid color selected" msgstr "" -#: src/ui/placePixel.js:222 +#: src/ui/PixelTransferController.js:116 msgid "Just for registered Users" msgstr "" -#: src/ui/placePixel.js:223 +#: src/ui/PixelTransferController.js:117 msgid "You have to be logged in to place on this canvas" msgstr "" -#: src/ui/placePixel.js:226 +#: src/ui/PixelTransferController.js:120 msgid "Place more :)" msgstr "" -#: src/ui/placePixel.js:228 +#: src/ui/PixelTransferController.js:122 msgid "You can not access this canvas yet. You need to place more pixels" msgstr "" -#: src/ui/placePixel.js:231 +#: src/ui/PixelTransferController.js:125 msgid "Pixel protected!" msgstr "" -#: src/ui/placePixel.js:238 +#: src/ui/PixelTransferController.js:132 msgid "Please prove that you are human" msgstr "" -#: src/ui/placePixel.js:242 +#: src/ui/PixelTransferController.js:136 msgid "No Proxies Allowed :(" msgstr "" -#: src/ui/placePixel.js:243 +#: src/ui/PixelTransferController.js:137 msgid "You are using a Proxy." msgstr "" -#: src/ui/placePixel.js:246 +#: src/ui/PixelTransferController.js:140 msgid "Not allowed" msgstr "" -#: src/ui/placePixel.js:247 +#: src/ui/PixelTransferController.js:141 msgid "Just the Top10 of yesterday can place here" msgstr "" -#: src/ui/placePixel.js:250 +#: src/ui/PixelTransferController.js:144 msgid "You are weird" msgstr "" -#: src/ui/placePixel.js:252 +#: src/ui/PixelTransferController.js:146 msgid "Server got confused by your pixels. Are you playing on multiple devices?" msgstr "" -#: src/ui/placePixel.js:255 +#: src/ui/PixelTransferController.js:149 msgid "Banned" msgstr "" -#: src/ui/placePixel.js:259 +#: src/ui/PixelTransferController.js:153 msgid "Range Banned" msgstr "" -#: src/ui/placePixel.js:260 +#: src/ui/PixelTransferController.js:154 msgid "Your Internet Provider is banned from playing this game" msgstr "" -#: src/ui/placePixel.js:263 +#: src/ui/PixelTransferController.js:157 +msgid "Timeout" +msgstr "" + +#: src/ui/PixelTransferController.js:159 +msgid "" +"Didn't get an answer from pixelplanet. Maybe try to refresh if problem " +"persists?" +msgstr "" + +#: src/ui/PixelTransferController.js:162 msgid "Weird" msgstr "" -#: src/ui/placePixel.js:264 +#: src/ui/PixelTransferController.js:163 msgid "Couldn't set Pixel" msgstr "" -#: src/ui/placePixel.js:269 +#: src/ui/PixelTransferController.js:168 #, javascript-format msgid "Error ${ retCode }" msgstr "" @@ -169,37 +179,38 @@ msgstr "" msgid "Can't render 3D canvas, do you have WebGL2 disabled?" msgstr "" -#: src/components/BanInfo.jsx:137 +#: src/components/BanInfo.jsx:136 #: src/store/actions/index.js:7 msgid "OK" msgstr "" -#: src/store/actions/fetch.js:39 +#: src/store/actions/fetch.js:55 msgid "You made too many requests" msgstr "" -#: src/store/actions/fetch.js:43 +#: src/store/actions/fetch.js:59 #, javascript-format msgid "try again after ${ ti }min" msgstr "" -#: src/store/actions/fetch.js:54 +#: src/store/actions/fetch.js:70 msgid "Connection error ${ code } :(" msgstr "" -#: src/store/actions/fetch.js:79 -#: src/store/actions/fetch.js:98 +#: src/store/actions/fetch.js:103 +#: src/store/actions/fetch.js:129 msgid "Could not connect to server, please try again later :(" msgstr "" -#: src/store/actions/fetch.js:120 -#: src/store/actions/fetch.js:139 -#: src/store/actions/fetch.js:158 -#: src/store/actions/fetch.js:177 +#: src/store/actions/fetch.js:151 +#: src/store/actions/fetch.js:170 +#: src/store/actions/fetch.js:189 +#: src/store/actions/fetch.js:208 +#: src/store/actions/fetch.js:227 msgid "Unknown Error" msgstr "" -#: src/store/actions/fetch.js:187 +#: src/store/actions/fetch.js:237 msgid "Server answered with gibberish :(" msgstr "" @@ -221,7 +232,7 @@ msgstr "" #: src/components/Converter.jsx:561 #: src/components/CoordinatesBox.jsx:31 -#: src/components/ModWatchtools.jsx:360 +#: src/components/ModWatchtools.jsx:371 msgid "Copy to Clipboard" msgstr "" @@ -237,6 +248,11 @@ msgstr "" msgid "Pixels placed" msgstr "" +#: src/components/buttons/CanvasSwitchButton.jsx:20 +#: src/components/windows/index.js:19 +msgid "Canvas Selection" +msgstr "" + #: src/components/buttons/ChatButton.jsx:88 msgid "Close Chat" msgstr "" @@ -253,27 +269,6 @@ msgstr "" msgid "Open Menu" msgstr "" -#: src/components/buttons/CanvasSwitchButton.jsx:22 -#: src/components/windows/index.js:19 -msgid "Canvas Selection" -msgstr "" - -#: src/store/actions/windows.js:98 -msgid "Register New Account" -msgstr "" - -#: src/store/actions/windows.js:105 -msgid "Restore my Password" -msgstr "" - -#: src/store/actions/windows.js:112 -msgid "Welcome to PixelPlanet.fun" -msgstr "" - -#: src/store/actions/windows.js:118 -msgid "Look at past Canvases" -msgstr "" - #: src/components/HistorySelect.jsx:144 msgid "Loading" msgstr "" @@ -282,51 +277,51 @@ msgstr "" msgid "Select Date above" msgstr "" -#: src/components/Admintools.jsx:101 -#: src/components/ModCanvastools.jsx:221 -#: src/components/ModWatchtools.jsx:110 -#: src/components/Window.jsx:153 -#: src/components/Window.jsx:254 +#: src/components/Admintools.jsx:103 +#: src/components/ModCanvastools.jsx:222 +#: src/components/ModWatchtools.jsx:118 +#: src/components/Window.jsx:157 +#: src/components/Window.jsx:260 #: src/components/contextmenus/ChannelContextMenu.jsx:59 msgid "Close" msgstr "" -#: src/components/Window.jsx:169 +#: src/components/Window.jsx:173 msgid "PopUp" msgstr "" -#: src/components/Window.jsx:180 +#: src/components/Window.jsx:184 msgid "Restore" msgstr "" -#: src/components/Window.jsx:215 +#: src/components/Window.jsx:221 msgid "Clone" msgstr "" -#: src/components/Window.jsx:223 +#: src/components/Window.jsx:229 msgid "Move" msgstr "" -#: src/components/Window.jsx:246 +#: src/components/Window.jsx:252 msgid "Maximize" msgstr "" -#: src/components/Window.jsx:262 +#: src/components/Window.jsx:268 msgid "Resize" msgstr "" -#: src/components/BanInfo.jsx:76 -#: src/components/buttons/HelpButton.jsx:22 +#: src/components/BanInfo.jsx:75 +#: src/components/buttons/HelpButton.jsx:20 #: src/components/windows/index.js:13 msgid "Help" msgstr "" -#: src/components/buttons/SettingsButton.jsx:22 +#: src/components/buttons/SettingsButton.jsx:21 #: src/components/windows/index.js:14 msgid "Settings" msgstr "" -#: src/components/buttons/LogInButton.jsx:22 +#: src/components/buttons/LogInButton.jsx:20 #: src/components/windows/index.js:15 msgid "User Area" msgstr "" @@ -335,10 +330,6 @@ msgstr "" msgid "Make Screenshot" msgstr "" -#: src/components/buttons/GlobeButton.jsx:34 -msgid "Globe View" -msgstr "" - #: src/components/buttons/PalselButton.jsx:30 msgid "Close Palette" msgstr "" @@ -347,6 +338,10 @@ msgstr "" msgid "Open Palette" msgstr "" +#: src/components/buttons/GlobeButton.jsx:34 +msgid "Globe View" +msgstr "" + #: src/components/windows/index.js:16 msgid "Registration" msgstr "" @@ -363,75 +358,95 @@ msgstr "" msgid "Canvas Archive" msgstr "" -#: src/components/BanInfo.jsx:67 -msgid "You are banned. You think it is unjustifed? Check out the " +#: src/components/GlobalCaptcha.jsx:50 +msgid "You took too long, try again." msgstr "" -#: src/components/BanInfo.jsx:77 -msgid " on how to appeal." +#: src/components/GlobalCaptcha.jsx:53 +msgid "You failed your captcha" msgstr "" -#: src/components/BanInfo.jsx:81 -#: src/components/Captcha.jsx:76 +#: src/components/GlobalCaptcha.jsx:56 +msgid "No or invalid captcha text" +msgstr "" + +#: src/components/GlobalCaptcha.jsx:59 +msgid "No captcha id given" +msgstr "" + +#: src/components/GlobalCaptcha.jsx:62 +msgid "Unknown Captcha Error" +msgstr "" + +#: src/components/BanInfo.jsx:80 +#: src/components/Captcha.jsx:77 #: src/components/ChangeMail.jsx:72 #: src/components/ChangeName.jsx:58 #: src/components/ChangePassword.jsx:79 #: src/components/DeleteAccount.jsx:55 -#: src/components/GlobalCaptcha.jsx:38 +#: src/components/GlobalCaptcha.jsx:74 #: src/components/LogInForm.jsx:70 -#: src/components/windows/ForgotPassword.jsx:75 -#: src/components/windows/Register.jsx:87 +#: src/components/windows/ForgotPassword.jsx:73 +#: src/components/windows/Register.jsx:89 msgid "Error" msgstr "" -#: src/components/BanInfo.jsx:86 -#: src/components/ModIIDtools.jsx:72 -msgid "Reason" -msgstr "" - -#: src/components/BanInfo.jsx:92 -msgid "By Mod" -msgstr "" - -#: src/components/BanInfo.jsx:98 -#: src/components/ModIIDtools.jsx:83 -msgid "Duration" -msgstr "" - -#: src/components/BanInfo.jsx:100 -msgid "Your ban expires at " -msgstr "" - -#: src/components/BanInfo.jsx:102 -msgid " which is in " -msgstr "" - -#: src/components/BanInfo.jsx:113 -msgid "Unbanned" -msgstr "" - -#: src/components/BanInfo.jsx:114 -msgid "Now that you have seen this message, you are no longer banned." -msgstr "" - -#: src/components/BanInfo.jsx:128 -msgid "Why?" -msgstr "" - #: src/components/ChangeMail.jsx:93 #: src/components/ChangeName.jsx:70 #: src/components/ChangePassword.jsx:115 #: src/components/DeleteAccount.jsx:68 -#: src/components/GlobalCaptcha.jsx:47 -#: src/components/windows/ForgotPassword.jsx:88 -#: src/components/windows/Register.jsx:131 +#: src/components/GlobalCaptcha.jsx:83 +#: src/components/windows/ForgotPassword.jsx:89 +#: src/components/windows/Register.jsx:133 msgid "Cancel" msgstr "" -#: src/components/GlobalCaptcha.jsx:53 +#: src/components/GlobalCaptcha.jsx:89 msgid "Send" msgstr "" +#: src/components/BanInfo.jsx:66 +msgid "You are banned. You think it is unjustifed? Check out the " +msgstr "" + +#: src/components/BanInfo.jsx:76 +msgid " on how to appeal." +msgstr "" + +#: src/components/BanInfo.jsx:85 +#: src/components/ModIIDtools.jsx:73 +msgid "Reason" +msgstr "" + +#: src/components/BanInfo.jsx:91 +msgid "By Mod" +msgstr "" + +#: src/components/BanInfo.jsx:97 +#: src/components/ModIIDtools.jsx:84 +msgid "Duration" +msgstr "" + +#: src/components/BanInfo.jsx:99 +msgid "Your ban expires at " +msgstr "" + +#: src/components/BanInfo.jsx:101 +msgid " which is in " +msgstr "" + +#: src/components/BanInfo.jsx:112 +msgid "Unbanned" +msgstr "" + +#: src/components/BanInfo.jsx:113 +msgid "Now that you have seen this message, you are no longer banned." +msgstr "" + +#: src/components/BanInfo.jsx:127 +msgid "Why?" +msgstr "" + #: src/components/windows/Help.jsx:42 msgid "Place color pixels on a large canvas with other players online!" msgstr "" @@ -698,83 +713,83 @@ msgstr "" msgid "Select Language" msgstr "" -#: src/components/windows/Register.jsx:85 +#: src/components/windows/UserArea.jsx:36 +#: src/components/windows/UserArea.jsx:56 +msgid "Profile" +msgstr "" + +#: src/components/windows/UserArea.jsx:59 +msgid "Statistics" +msgstr "" + +#: src/components/windows/UserArea.jsx:64 +msgid "Converter" +msgstr "" + +#: src/components/windows/UserArea.jsx:70 +msgid "Modtools" +msgstr "" + +#: src/components/windows/UserArea.jsx:71 +msgid "Loading..." +msgstr "" + +#: src/components/windows/UserArea.jsx:78 +msgid "Consider joining us on Guilded:" +msgstr "" + +#: src/components/windows/Register.jsx:87 msgid "Register new account here" msgstr "" -#: src/components/windows/Register.jsx:90 -#: src/components/windows/Register.jsx:96 +#: src/components/windows/Register.jsx:92 +#: src/components/windows/Register.jsx:98 msgid "Name" msgstr "" -#: src/components/windows/ForgotPassword.jsx:82 -#: src/components/windows/Register.jsx:98 -#: src/components/windows/Register.jsx:104 +#: src/components/windows/ForgotPassword.jsx:80 +#: src/components/windows/Register.jsx:100 +#: src/components/windows/Register.jsx:106 msgid "Email" msgstr "" #: src/components/ChangeMail.jsx:80 #: src/components/DeleteAccount.jsx:62 #: src/components/LogInForm.jsx:84 -#: src/components/windows/Register.jsx:106 -#: src/components/windows/Register.jsx:112 +#: src/components/windows/Register.jsx:108 +#: src/components/windows/Register.jsx:114 msgid "Password" msgstr "" -#: src/components/windows/Register.jsx:114 -#: src/components/windows/Register.jsx:120 +#: src/components/windows/Register.jsx:116 +#: src/components/windows/Register.jsx:122 msgid "Confirm Password" msgstr "" -#: src/components/windows/Register.jsx:122 +#: src/components/windows/Register.jsx:124 msgid "Captcha" msgstr "" -#: src/components/Admintools.jsx:152 -#: src/components/Admintools.jsx:236 -#: src/components/ModCanvastools.jsx:301 -#: src/components/ModCanvastools.jsx:381 -#: src/components/ModCanvastools.jsx:454 -#: src/components/ModCanvastools.jsx:545 -#: src/components/ModIIDtools.jsx:134 -#: src/components/windows/ForgotPassword.jsx:86 -#: src/components/windows/Register.jsx:125 +#: src/components/Admintools.jsx:154 +#: src/components/Admintools.jsx:238 +#: src/components/ModCanvastools.jsx:302 +#: src/components/ModCanvastools.jsx:382 +#: src/components/ModCanvastools.jsx:455 +#: src/components/ModCanvastools.jsx:546 +#: src/components/ModIIDtools.jsx:135 +#: src/components/windows/ForgotPassword.jsx:84 +#: src/components/windows/Register.jsx:127 msgid "Submit" msgstr "" -#: src/components/windows/UserArea.jsx:31 -#: src/components/windows/UserArea.jsx:50 -msgid "Profile" -msgstr "" - -#: src/components/windows/UserArea.jsx:53 -msgid "Ranking" -msgstr "" - -#: src/components/windows/UserArea.jsx:56 -msgid "Converter" -msgstr "" - -#: src/components/windows/UserArea.jsx:62 -msgid "Modtools" -msgstr "" - -#: src/components/windows/UserArea.jsx:63 -msgid "Loading..." -msgstr "" - -#: src/components/windows/UserArea.jsx:70 -msgid "Consider joining us on Guilded:" -msgstr "" - -#: src/components/windows/CanvasSelect.jsx:27 +#: src/components/windows/CanvasSelect.jsx:29 msgid "" "Select the canvas you want to use. Every canvas is unique and has " "different palettes, cooldown and requirements. Archive of closed canvases " "can be accessed here:" msgstr "" -#: src/components/windows/CanvasSelect.jsx:35 +#: src/components/windows/CanvasSelect.jsx:37 msgid "Archive" msgstr "" @@ -811,60 +826,60 @@ msgid "" "how the canvas was at that time." msgstr "" -#: src/components/windows/Chat.jsx:176 +#: src/components/windows/Chat.jsx:180 msgid "Start chatting here" msgstr "" -#: src/components/windows/Chat.jsx:213 +#: src/components/windows/Chat.jsx:217 msgid "Chat here" msgstr "" -#: src/components/windows/Chat.jsx:239 +#: src/components/windows/Chat.jsx:243 msgid "You must be logged in to chat" msgstr "" -#: src/components/windows/Chat.jsx:268 +#: src/components/windows/Chat.jsx:273 msgid "Channel settings" msgstr "" -#: src/components/windows/ForgotPassword.jsx:60 +#: src/components/windows/ForgotPassword.jsx:58 msgid "Sent you a mail with instructions to reset your password." msgstr "" -#: src/components/windows/ForgotPassword.jsx:71 +#: src/components/windows/ForgotPassword.jsx:69 msgid "Enter your mail address and we will send you a new password:" msgstr "" -#: src/components/Captcha.jsx:50 -#: src/components/Captcha.jsx:104 +#: src/components/Captcha.jsx:51 +#: src/components/Captcha.jsx:105 msgid "Could not load captcha" msgstr "" -#: src/components/Captcha.jsx:68 +#: src/components/Captcha.jsx:69 msgid "Type the characters from the following image:" msgstr "" -#: src/components/Captcha.jsx:71 +#: src/components/Captcha.jsx:72 msgid "Tip: Not case-sensitive; I and l are the same" msgstr "" -#: src/components/Captcha.jsx:113 +#: src/components/Captcha.jsx:114 msgid "Load Captcha" msgstr "" -#: src/components/Captcha.jsx:118 +#: src/components/Captcha.jsx:119 msgid "Click to Load Captcha" msgstr "" -#: src/components/Captcha.jsx:123 +#: src/components/Captcha.jsx:124 msgid "Can't read? Reload:" msgstr "" -#: src/components/Captcha.jsx:127 +#: src/components/Captcha.jsx:128 msgid "Reload" msgstr "" -#: src/components/Captcha.jsx:137 +#: src/components/Captcha.jsx:138 msgid "Enter Characters" msgstr "" @@ -927,31 +942,31 @@ msgstr "" #: src/components/ChangeMail.jsx:91 #: src/components/ChangeName.jsx:68 #: src/components/ChangePassword.jsx:109 -#: src/components/LanguageSelect.jsx:73 +#: src/components/LanguageSelect.jsx:80 msgid "Save" msgstr "" -#: src/components/LogInArea.jsx:20 +#: src/components/LogInArea.jsx:19 msgid "Login to access more features and stats." msgstr "" -#: src/components/LogInArea.jsx:22 +#: src/components/LogInArea.jsx:21 msgid "Login with Name or Mail:" msgstr "" -#: src/components/LogInArea.jsx:29 +#: src/components/LogInArea.jsx:28 msgid "I forgot my Password." msgstr "" -#: src/components/LogInArea.jsx:30 +#: src/components/LogInArea.jsx:29 msgid "or login with:" msgstr "" -#: src/components/LogInArea.jsx:71 +#: src/components/LogInArea.jsx:70 msgid "or register here:" msgstr "" -#: src/components/LogInArea.jsx:78 +#: src/components/LogInArea.jsx:75 msgid "Register" msgstr "" @@ -1000,20 +1015,8 @@ msgstr "" msgid "Social Settings" msgstr "" -#: src/components/Rankings.jsx:31 -msgid "Total" -msgstr "" - -#: src/components/Rankings.jsx:40 -msgid "Daily" -msgstr "" - -#: src/components/Rankings.jsx:88 -msgid "Ranking updates every 5 min. Daily rankings get reset at midnight UTC." -msgstr "" - #: src/components/Converter.jsx:190 -#: src/components/ModCanvastools.jsx:225 +#: src/components/ModCanvastools.jsx:226 msgid "Choose Canvas" msgstr "" @@ -1091,6 +1094,40 @@ msgstr "" msgid "Download Template" msgstr "" +#: src/components/Rankings.jsx:147 +msgid "Total" +msgstr "" + +#: src/components/Rankings.jsx:156 +msgid "Today" +msgstr "" + +#: src/components/Rankings.jsx:165 +msgid "Yesterday" +msgstr "" + +#: src/components/Rankings.jsx:174 +msgid "Countries Today" +msgstr "" + +#: src/components/Rankings.jsx:183 +msgid "Charts" +msgstr "" + +#: src/components/Rankings.jsx:201 +#: src/components/Rankings.jsx:210 +#: src/components/Rankings.jsx:219 +msgid "User" +msgstr "" + +#: src/components/Rankings.jsx:226 +msgid "Country" +msgstr "" + +#: src/components/Rankings.jsx:286 +msgid "Ranking updates every 5 min. Daily rankings get reset at midnight UTC." +msgstr "" + #: src/components/CanvasItem.jsx:29 msgid "Online Users" msgstr "" @@ -1136,6 +1173,26 @@ msgstr "" msgid "Dimensions" msgstr "" +#: src/core/chartSettings.js:30 +msgid "Top 10 Countries [pxls / day]" +msgstr "" + +#: src/core/chartSettings.js:127 +msgid "Players and Pixels per hour" +msgstr "" + +#: src/core/chartSettings.js:221 +msgid "Top 10 Players [pxls / day]" +msgstr "" + +#: src/core/chartSettings.js:294 +msgid "Countries by Pixels Today" +msgstr "" + +#: src/core/chartSettings.js:352 +msgid "Total Pixels placed per day" +msgstr "" + #: src/components/LogInForm.jsx:77 msgid "Name or Email" msgstr "" @@ -1144,6 +1201,20 @@ msgstr "" msgid "LogIn" msgstr "" +#: src/components/UserMessages.jsx:28 +msgid "" +"Please verify your mail address or your account could get deleted after a " +"few days." +msgstr "" + +#: src/components/UserMessages.jsx:49 +msgid "A new verification mail is getting sent to you." +msgstr "" + +#: src/components/UserMessages.jsx:53 +msgid "Click here to request a new verification mail." +msgstr "" + #: src/components/ChangePassword.jsx:21 msgid "Passwords do not match." msgstr "" @@ -1178,206 +1249,204 @@ msgstr "" msgid "New Mail" msgstr "" -#: src/components/UserMessages.jsx:28 -msgid "" -"Please verify your mail address or your account could get deleted after a " -"few days." -msgstr "" - -#: src/components/UserMessages.jsx:49 -msgid "A new verification mail is getting sent to you." -msgstr "" - -#: src/components/UserMessages.jsx:53 -msgid "Click here to request a new verification mail." -msgstr "" - #: src/components/DeleteAccount.jsx:66 msgid "Yes, Delete My Account!" msgstr "" -#: src/components/SocialSettings.jsx:24 +#: src/components/SocialSettings.jsx:35 +msgid "Block DMs" +msgstr "" + +#: src/components/SocialSettings.jsx:42 msgid "Block all Private Messages" msgstr "" -#: src/components/SocialSettings.jsx:37 +#: src/components/SocialSettings.jsx:44 +msgid "Private" +msgstr "" + +#: src/components/SocialSettings.jsx:51 +msgid "Don't show me in global stats" +msgstr "" + +#: src/components/SocialSettings.jsx:57 msgid "Unblock Users" msgstr "" -#: src/components/SocialSettings.jsx:62 +#: src/components/SocialSettings.jsx:82 msgid "You have no users blocked" msgstr "" -#: src/components/ModCanvastools.jsx:167 +#: src/components/ModCanvastools.jsx:168 msgid "Build image on canvas." msgstr "" -#: src/components/ModCanvastools.jsx:170 +#: src/components/ModCanvastools.jsx:171 msgid "Build image and set it to protected." msgstr "" -#: src/components/ModCanvastools.jsx:173 +#: src/components/ModCanvastools.jsx:174 msgid "Build image, but reset cooldown to unset-pixel cd." msgstr "" -#: src/components/ModCanvastools.jsx:183 +#: src/components/ModCanvastools.jsx:184 msgid "Clean spare pixels that are surrounded by unset pixels" msgstr "" -#: src/components/ModCanvastools.jsx:187 +#: src/components/ModCanvastools.jsx:188 msgid "" "Clean spare pixels that are surrounded by unset pixels and up to 1 other " "set pixels" msgstr "" -#: src/components/ModCanvastools.jsx:191 +#: src/components/ModCanvastools.jsx:192 msgid "" "Clean spare pixels that are surrounded by a single other color or unset " "pixels (VERY AGGRESSIVE ON CANVASES THAT ALLOW UNSET PIXELS (where there " "are two cooldowns)!)" msgstr "" -#: src/components/ModCanvastools.jsx:202 +#: src/components/ModCanvastools.jsx:203 msgid "Status: Not running" msgstr "" -#: src/components/ModCanvastools.jsx:244 +#: src/components/ModCanvastools.jsx:245 msgid "Image Upload" msgstr "" -#: src/components/ModCanvastools.jsx:245 +#: src/components/ModCanvastools.jsx:246 msgid "Upload images to canvas" msgstr "" -#: src/components/ModCanvastools.jsx:247 +#: src/components/ModCanvastools.jsx:248 msgid "File" msgstr "" -#: src/components/ModCanvastools.jsx:268 +#: src/components/ModCanvastools.jsx:269 msgid "Coordinates in X_Y format:" msgstr "" -#: src/components/ModCanvastools.jsx:306 +#: src/components/ModCanvastools.jsx:307 msgid "Pixel Protection" msgstr "" -#: src/components/ModCanvastools.jsx:308 +#: src/components/ModCanvastools.jsx:309 msgid "" "Set protection of areas (if you need finer grained control, " "use protect with image upload and alpha layers)" msgstr "" -#: src/components/ModCanvastools.jsx:329 -#: src/components/ModCanvastools.jsx:402 -#: src/components/ModCanvastools.jsx:485 -#: src/components/ModWatchtools.jsx:166 +#: src/components/ModCanvastools.jsx:330 +#: src/components/ModCanvastools.jsx:403 +#: src/components/ModCanvastools.jsx:486 +#: src/components/ModWatchtools.jsx:174 msgid "Top-left corner" msgstr "" -#: src/components/ModCanvastools.jsx:346 -#: src/components/ModCanvastools.jsx:419 -#: src/components/ModCanvastools.jsx:502 -#: src/components/ModWatchtools.jsx:183 +#: src/components/ModCanvastools.jsx:347 +#: src/components/ModCanvastools.jsx:420 +#: src/components/ModCanvastools.jsx:503 +#: src/components/ModWatchtools.jsx:191 msgid "Bottom-right corner" msgstr "" -#: src/components/ModCanvastools.jsx:387 +#: src/components/ModCanvastools.jsx:388 msgid "Rollback to Date" msgstr "" -#: src/components/ModCanvastools.jsx:389 +#: src/components/ModCanvastools.jsx:390 msgid "Rollback an area of the canvas to a set date (00:00 UTC)" msgstr "" -#: src/components/ModCanvastools.jsx:460 +#: src/components/ModCanvastools.jsx:461 msgid "Canvas Cleaner" msgstr "" -#: src/components/ModCanvastools.jsx:462 +#: src/components/ModCanvastools.jsx:463 msgid "Apply a filter to clean trash in large canvas areas." msgstr "" -#: src/components/ModCanvastools.jsx:563 +#: src/components/ModCanvastools.jsx:564 msgid "Stop Cleaner" msgstr "" -#: src/components/Admintools.jsx:107 +#: src/components/Admintools.jsx:109 msgid "IP Actions" msgstr "" -#: src/components/Admintools.jsx:109 +#: src/components/Admintools.jsx:111 msgid "Do stuff with IPs (one IP per line)" msgstr "" -#: src/components/Admintools.jsx:156 +#: src/components/Admintools.jsx:158 msgid "Manage Moderators" msgstr "" -#: src/components/Admintools.jsx:158 +#: src/components/Admintools.jsx:160 msgid "Remove Moderator" msgstr "" -#: src/components/Admintools.jsx:191 +#: src/components/Admintools.jsx:193 msgid "There are no mods" msgstr "" -#: src/components/Admintools.jsx:196 +#: src/components/Admintools.jsx:198 msgid "Assign new Mod" msgstr "" -#: src/components/Admintools.jsx:199 +#: src/components/Admintools.jsx:201 msgid "Enter UserName of new Mod" msgstr "" -#: src/components/Admintools.jsx:208 +#: src/components/Admintools.jsx:210 msgid "User Name" msgstr "" -#: src/components/ModWatchtools.jsx:45 +#: src/components/ModWatchtools.jsx:48 msgid "Interval is invalid" msgstr "" -#: src/components/ModWatchtools.jsx:114 +#: src/components/ModWatchtools.jsx:122 msgid "Check who placed in an area" msgstr "" -#: src/components/ModWatchtools.jsx:115 +#: src/components/ModWatchtools.jsx:123 msgid "Canvas" msgstr "" -#: src/components/ModWatchtools.jsx:134 +#: src/components/ModWatchtools.jsx:142 msgid "Interval" msgstr "" -#: src/components/ModWatchtools.jsx:149 +#: src/components/ModWatchtools.jsx:157 msgid "IID (optional)" msgstr "" -#: src/components/ModWatchtools.jsx:228 +#: src/components/ModWatchtools.jsx:236 msgid "Get Pixels" msgstr "" -#: src/components/ModWatchtools.jsx:259 +#: src/components/ModWatchtools.jsx:267 msgid "Get Users" msgstr "" -#: src/components/ModIIDtools.jsx:19 +#: src/components/ModIIDtools.jsx:20 msgid "You must enter a duration" msgstr "" -#: src/components/ModIIDtools.jsx:23 +#: src/components/ModIIDtools.jsx:24 msgid "You must enter an IID" msgstr "" -#: src/components/ModIIDtools.jsx:52 +#: src/components/ModIIDtools.jsx:53 msgid "IID Actions" msgstr "" -#: src/components/ModIIDtools.jsx:79 +#: src/components/ModIIDtools.jsx:80 msgid "Enter Reason" msgstr "" -#: src/components/ModIIDtools.jsx:96 +#: src/components/ModIIDtools.jsx:97 msgid "(0 = infinite)" msgstr "" diff --git a/src/client.js b/src/client.js index c595561..52c7e60 100644 --- a/src/client.js +++ b/src/client.js @@ -14,14 +14,11 @@ import { import { fetchMe, } from './store/actions/thunks'; -import { - receivePixelUpdate, - receivePixelReturn, -} from './ui/placePixel'; +import pixelTransferController from './ui/PixelTransferController'; import store from './store/store'; import renderApp from './components/App'; import { initRenderer, getRenderer } from './ui/renderer'; -import SocketClient from './socket/SocketClient'; +import socketClient from './socket/SocketClient'; persistStore(store, {}, () => { window.addEventListener('message', store.dispatch); @@ -30,32 +27,19 @@ persistStore(store, {}, () => { initRenderer(store, false); - SocketClient.on('pixelUpdate', ({ - i, j, pixels, - }) => { - pixels.forEach((pxl) => { - const [offset, color] = pxl; - // remove protection - receivePixelUpdate(getRenderer(), i, j, offset, color & 0x7F); - }); - }); - SocketClient.on('pixelReturn', (args) => { - receivePixelReturn(store, getRenderer(), args); - }); + pixelTransferController.initialize(store, socketClient, getRenderer); window.addEventListener('hashchange', () => { store.dispatch(urlChange()); }); // check if on mobile - // function checkMobile() { store.dispatch(setMobile(true)); } document.addEventListener('touchstart', checkMobile, { once: true }); // listen for resize - // function onWindowResize() { store.dispatch(windowResize()); } @@ -65,7 +49,8 @@ persistStore(store, {}, () => { store.dispatch(initTimer()); store.dispatch(fetchMe()); - SocketClient.initialize(store); + + socketClient.initialize(store); }); (function load() { @@ -90,7 +75,7 @@ persistStore(store, {}, () => { if (!renderer.isChunkInView(zc, xc, yc)) { cnt++; if (value.isBasechunk) { - SocketClient.deRegisterChunk([xc, yc]); + socketClient.deRegisterChunk([xc, yc]); } chunks.delete(key); value.destructor(); diff --git a/src/components/GlobalCaptcha.jsx b/src/components/GlobalCaptcha.jsx index 18ba687..d80f685 100644 --- a/src/components/GlobalCaptcha.jsx +++ b/src/components/GlobalCaptcha.jsx @@ -42,7 +42,6 @@ const GlobalCaptcha = ({ close }) => { setSubmitting(true); const retCode = await socketClient .sendCaptchaSolution(text, captchaid); - console.log('Captcha return:', retCode); switch (retCode) { case 0: close(); diff --git a/src/controls/PixelPainterControls.js b/src/controls/PixelPainterControls.js index 5e24b73..2175e1f 100644 --- a/src/controls/PixelPainterControls.js +++ b/src/controls/PixelPainterControls.js @@ -20,9 +20,7 @@ import { moveEast, onViewFinishChange, } from '../store/actions'; -import { - tryPlacePixel, -} from '../ui/placePixel'; +import pixelTransferController from '../ui/PixelTransferController'; import { screenToWorld, getChunkOfPixel, @@ -245,9 +243,7 @@ class PixelPlainterControls { } const [i, j] = getChunkOfPixel(canvasSize, x, y); const offset = getOffsetOfPixel(canvasSize, x, y); - tryPlacePixel( - renderer, - store, + pixelTransferController.tryPlacePixel( i, j, offset, selectedColor, curColor, diff --git a/src/socket/SocketClient.js b/src/socket/SocketClient.js index 0381777..8dd056b 100644 --- a/src/socket/SocketClient.js +++ b/src/socket/SocketClient.js @@ -1,8 +1,6 @@ // allow the websocket to be noisy on the console /* eslint-disable no-console */ -import EventEmitter from 'events'; - import { hydratePixelUpdate, hydratePixelReturn, @@ -37,12 +35,12 @@ import { fetchMe, } from '../store/actions/thunks'; import { shardHost } from '../store/actions/fetch'; +import pixelTransferController from '../ui/PixelTransferController'; const chunks = []; -class SocketClient extends EventEmitter { +class SocketClient { constructor() { - super(); console.log('Creating WebSocketClient'); this.store = null; this.ws = null; @@ -186,8 +184,8 @@ class SocketClient extends EventEmitter { sendCaptchaSolution(solution, captchaid) { return new Promise((resolve, reject) => { let id; - const queueObj = ['cs', (args) => { - resolve(args); + const queueObj = ['cs', (arg) => { + resolve(arg); clearTimeout(id); }]; this.reqQueue.push(queueObj); @@ -207,12 +205,21 @@ class SocketClient extends EventEmitter { * @param i, j chunk coordinates * @param pixel Array of [[offset, color],...] pixels within chunk */ - requestPlacePixels( - i, j, - pixels, - ) { - const buffer = dehydratePixelUpdate(i, j, pixels); - this.sendWhenReady(buffer); + sendPixelUpdate(i, j, pixels) { + return new Promise((resolve, reject) => { + let id; + const queueObj = ['pu', (arg) => { + resolve(arg); + clearTimeout(id); + }]; + this.reqQueue.push(queueObj); + id = setTimeout(() => { + const pos = this.reqQueue.indexOf(queueObj); + if (~pos) this.reqQueue.splice(pos, 1); + reject(new Error('Timeout')); + }, 20000); + this.sendWhenReady(dehydratePixelUpdate(i, j, pixels)); + }); } sendChatMessage(message, channelId) { @@ -267,11 +274,15 @@ class SocketClient extends EventEmitter { switch (opcode) { case PIXEL_UPDATE_OP: - this.emit('pixelUpdate', hydratePixelUpdate(data)); + pixelTransferController.receivePixelUpdate(hydratePixelUpdate(data)); break; - case PIXEL_RETURN_OP: - this.emit('pixelReturn', hydratePixelReturn(data)); + case PIXEL_RETURN_OP: { + const pos = this.reqQueue.findIndex((q) => q[0] === 'pu'); + if (~pos) { + this.reqQueue.splice(pos, 1)[0][1](hydratePixelReturn(data)); + } break; + } case ONLINE_COUNTER_OP: this.store.dispatch(receiveOnline(hydrateOnlineCounter(data))); break; diff --git a/src/store/actions/index.js b/src/store/actions/index.js index ce30d4a..0efcb5b 100644 --- a/src/store/actions/index.js +++ b/src/store/actions/index.js @@ -106,12 +106,6 @@ export function toggleOpenMenu() { }; } -export function requestPlaceTimeout() { - return { - type: 'REQ_PLACE_TIMEOUT', - }; -} - export function setHover(hover) { return { type: 'SET_HOVER', @@ -298,22 +292,6 @@ export function sendChatMessage( }; } -/* - * check socket/packets/PixelReturn.js for args - */ -export function storeReceivePixelReturn(args) { - args.type = 'REC_PXL_RETURN'; - return args; -} -export function requestPlacePixels(i, j, pixels) { - return { - type: 'REQ_PLACE_PXLS', - i, - j, - pixels, - }; -} - export function logoutUser( ) { return { diff --git a/src/store/actions/socket.js b/src/store/actions/socket.js index 5a3110f..0dd5d08 100644 --- a/src/store/actions/socket.js +++ b/src/store/actions/socket.js @@ -23,11 +23,17 @@ export function receiveChatMessage( return (dispatch, getState) => { channel = Number(channel); const state = getState(); - const isRead = state.windows.showWindows - // eslint-disable-next-line max-len - && state.windows.windows.find((win) => win.windowType === 'CHAT' && !win.hidden) - // eslint-disable-next-line max-len - && Object.values(state.windows.args).find((args) => args.chatChannel === channel); + let isRead = false; + if (state.windows) { + isRead = state.windows.windows.some( + (win) => win.windowType === 'CHAT' && !win.hidden, + ) && Object.values(state.windows.args).some( + (args) => args.chatChannel === channel, + ); + } else { + isRead = state.popup.windowType === 'CHAT' + || state.popup.args.chatChannel === channel; + } // TODO ping doesn't work since update // const { nameRegExp } = state.user; @@ -40,7 +46,7 @@ export function receiveChatMessage( channel, user, isPing: false, - isRead: !!isRead, + isRead, }); }; } @@ -72,3 +78,15 @@ export function removeChatChannel(cid) { cid, }; } + +export function setPixelsFetching(fetching) { + return { + type: 'SET_PXLS_FETCHING', + fetching, + }; +} + +export function receivePlacePixels(args) { + args.type = 'REC_SET_PXLS'; + return args; +} diff --git a/src/store/middleware/audio.js b/src/store/middleware/audio.js index c8db91e..3093b10 100644 --- a/src/store/middleware/audio.js +++ b/src/store/middleware/audio.js @@ -119,7 +119,7 @@ export default (store) => (next) => (action) => { break; } - case 'REC_PXL_RETURN': { + case 'REC_SET_PXLS': { switch (action.retCode) { case 0: { // successfully placed pixel diff --git a/src/store/middleware/rendererHook.js b/src/store/middleware/rendererHook.js index 4c66d3d..72b85dd 100644 --- a/src/store/middleware/rendererHook.js +++ b/src/store/middleware/rendererHook.js @@ -114,7 +114,7 @@ export default (store) => (next) => (action) => { break; } - case 'REC_PXL_RETURN': { + case 'REC_SET_PXLS': { const renderer = getRenderer(); renderer.forceNextSubrender = true; const { coolDownSeconds } = action; diff --git a/src/store/middleware/socketClientHook.js b/src/store/middleware/socketClientHook.js index 4bdfb3c..d58edfe 100644 --- a/src/store/middleware/socketClientHook.js +++ b/src/store/middleware/socketClientHook.js @@ -24,14 +24,6 @@ export default (store) => (next) => (action) => { break; } - case 'REQ_PLACE_PXLS': { - const { - i, j, pixels, - } = action; - SocketClient.requestPlacePixels(i, j, pixels); - break; - } - case 's/REQ_CHAT_MESSAGE': { const { text, diff --git a/src/store/reducers/fetching.js b/src/store/reducers/fetching.js index 88dad4b..09d3852 100644 --- a/src/store/reducers/fetching.js +++ b/src/store/reducers/fetching.js @@ -6,6 +6,7 @@ const initialState = { fetchingChunks: 0, fetchingChat: false, + fetchingPixel: false, fetchinApi: false, }; @@ -59,6 +60,14 @@ export default function fetching( }; } + case 'SET_PXLS_FETCHING': { + const { fetching: fetchingPixel } = action; + return { + ...state, + fetchingPixel, + }; + } + default: return state; } diff --git a/src/store/reducers/ranks.js b/src/store/reducers/ranks.js index db45923..c12009c 100644 --- a/src/store/reducers/ranks.js +++ b/src/store/reducers/ranks.js @@ -31,7 +31,7 @@ export default function ranks( action, ) { switch (action.type) { - case 'REC_PXL_RETURN': { + case 'REC_SET_PXLS': { const { rankedPxlCnt, } = action; diff --git a/src/store/reducers/user.js b/src/store/reducers/user.js index a81f20d..a9eb6bb 100644 --- a/src/store/reducers/user.js +++ b/src/store/reducers/user.js @@ -4,7 +4,6 @@ const initialState = { wait: null, coolDown: null, // ms lastCoolDownEnd: null, - allowSettingPixel: true, // messages are sent by api/me, like not_verified status messages: [], mailreg: false, @@ -42,28 +41,13 @@ export default function user( }; } - case 'REQ_PLACE_TIMEOUT': { - return { - ...state, - allowSettingPixel: true, - }; - } - - case 'REQ_PLACE_PXLS': { - return { - ...state, - allowSettingPixel: false, - }; - } - - case 'REC_PXL_RETURN': { + case 'REC_SET_PXLS': { const { wait: duration, } = action; return { ...state, wait: (duration) ? Date.now() + duration : state.wait, - allowSettingPixel: true, }; } diff --git a/src/ui/PixelTransferController.js b/src/ui/PixelTransferController.js new file mode 100644 index 0000000..2d40b11 --- /dev/null +++ b/src/ui/PixelTransferController.js @@ -0,0 +1,269 @@ +/* + * Control in- and outcomming pixels, + * do client prediction, send to draw on renderer + */ +import { t } from 'ttag'; +import { + pAlert, +} from '../store/actions'; +import { + setPixelsFetching, + receivePlacePixels, +} from '../store/actions/socket'; +import { + notify, +} from '../store/actions/thunks'; + +class PixelTransferController { + constructor() { + this.requestFromQueue = this.requestFromQueue.bind(this); + /* + * cache of pixels that still are to set + * [{i: i, j: j, pixels: [[offset, color],...]}, ...] + */ + this.pixelQueue = []; + /* + * requests that got predicted on client and yet have to be + * received from the server + * [[i, j, offset, colorold, colornew], ...] + */ + this.clientPredictions = []; + } + + initialize(store, socketClient, getRenderer) { + this.store = store; + this.socketClient = socketClient; + this.getRenderer = getRenderer; + } + + /* + * request pixel placement from queue + */ + async requestFromQueue() { + const { store } = this; + if (!this.pixelQueue.length) { + store.dispatch(setPixelsFetching(false)); + return; + } + + store.dispatch(setPixelsFetching(true)); + const { i, j, pixels } = this.pixelQueue.shift(); + + let ret; + try { + ret = await this.socketClient.sendPixelUpdate(i, j, pixels); + } catch { + // timeout + ret = { + retCode: 16, + coolDownSeconds: 0, + pxlCnt: 0, + }; + store.dispatch(pAlert( + t`Error :(`, + t`Didn't get an answer from pixelplanet. Maybe try to refresh?`, + 'error', + )); + } + + const { + retCode, + coolDownSeconds, + pxlCnt, + } = ret; + + if (coolDownSeconds) { + store.dispatch(notify(coolDownSeconds)); + } + + if (retCode) { + /* + * one or more pixels didn't get set, + * revert predictions and clean queue + */ + const [offset] = pixels[pxlCnt]; + this.revertPredictionsAt(i, j, offset); + this.pixelQueue = []; + } + + let errorTitle = null; + let msg = null; + let type = 'error'; + switch (retCode) { + case 0: + break; + case 1: + errorTitle = t`Invalid Canvas`; + msg = t`This canvas doesn't exist`; + break; + case 2: + errorTitle = t`Invalid Coordinates`; + msg = t`x out of bounds`; + break; + case 3: + errorTitle = t`Invalid Coordinates`; + msg = t`y out of bounds`; + break; + case 4: + errorTitle = t`Invalid Coordinates`; + msg = t`z out of bounds`; + break; + case 5: + errorTitle = t`Wrong Color`; + msg = t`Invalid color selected`; + break; + case 6: + errorTitle = t`Just for registered Users`; + msg = t`You have to be logged in to place on this canvas`; + break; + case 7: + errorTitle = t`Place more :)`; + // eslint-disable-next-line max-len + msg = t`You can not access this canvas yet. You need to place more pixels`; + break; + case 8: + store.dispatch(notify(t`Pixel protected!`)); + break; + case 9: + // pixestack used up + break; + case 10: + errorTitle = 'Captcha'; + msg = t`Please prove that you are human`; + type = 'captcha'; + break; + case 11: + errorTitle = t`No Proxies Allowed :(`; + msg = t`You are using a Proxy.`; + break; + case 12: + errorTitle = t`Not allowed`; + msg = t`Just the Top10 of yesterday can place here`; + break; + case 13: + errorTitle = t`You are weird`; + // eslint-disable-next-line max-len + msg = t`Server got confused by your pixels. Are you playing on multiple devices?`; + break; + case 14: + errorTitle = t`Banned`; + type = 'ban'; + break; + case 15: + errorTitle = t`Range Banned`; + msg = t`Your Internet Provider is banned from playing this game`; + break; + case 16: + errorTitle = t`Timeout`; + // eslint-disable-next-line max-len + msg = t`Didn't get an answer from pixelplanet. Maybe try to refresh if problem persists?`; + break; + default: + errorTitle = t`Weird`; + msg = t`Couldn't set Pixel`; + } + + if (msg || errorTitle) { + store.dispatch(pAlert( + (errorTitle || t`Error ${retCode}`), + msg, + type, + )); + } + + store.dispatch(receivePlacePixels(ret)); + setTimeout(this.requestFromQueue, 100); + } + + /* + * Revert predictions starting at given pixel + * @param i, j, offset data of the first pixel that got rejected + */ + revertPredictionsAt(sI, sJ, sOffset) { + const renderer = this.getRenderer(); + const { clientPredictions } = this; + let p = 0; + while (p < clientPredictions.length) { + const predPxl = clientPredictions[p]; + if (predPxl[0] === sI + && predPxl[1] === sJ + && predPxl[2] === sOffset + ) { + break; + } + p += 1; + } + + while (p < clientPredictions.length) { + const [i, j, offset, color] = clientPredictions[p]; + renderer.renderPixel(i, j, offset, color, false); + p += 1; + } + + this.clientPredictions = []; + } + + /* + * got pixel update from websocket + */ + receivePixelUpdate({ + i, + j, + pixels, + }) { + pixels.forEach((pxl) => { + const [offset, color] = pxl; + const { clientPredictions } = this; + for (let p = 0; p < clientPredictions.length; p += 1) { + const predPxl = clientPredictions[p]; + if (predPxl[0] === i + && predPxl[1] === j + && predPxl[2] === offset + ) { + if (predPxl[4] === color) { + clientPredictions.splice(p, 1); + } + return; + } + } + this.getRenderer().renderPixel(i, j, offset, color, true); + }); + } + + /* + * try to place a pixel + */ + tryPlacePixel( + i, + j, + offset, + color, + curColor, + ) { + this.getRenderer().renderPixel(i, j, offset, color, false); + this.clientPredictions.push([i, j, offset, curColor, color]); + const { pixelQueue } = this; + + if (pixelQueue.length) { + const lastReq = pixelQueue[pixelQueue.length - 1]; + const { i: lastI, j: lastJ } = lastReq; + if (i === lastI && j === lastJ) { + /* append to last request in queue if same chunk */ + lastReq.pixels.push([offset, color]); + } + return; + } + + pixelQueue.push({ + i, + j, + pixels: [[offset, color]], + }); + + if (!this.store.getState().fetching.fetchingPixel) { + this.requestFromQueue(); + } + } +} + +export default new PixelTransferController(); diff --git a/src/ui/Renderer2D.js b/src/ui/Renderer2D.js index e533261..f37089d 100644 --- a/src/ui/Renderer2D.js +++ b/src/ui/Renderer2D.js @@ -427,8 +427,8 @@ class Renderer { isLightGrid, } = state.gui; const { - allowSettingPixel, - } = state.user; + fetchingPixel, + } = state.fetching; const { view, viewscale, @@ -448,13 +448,13 @@ class Renderer { // if we have to render placeholder const doRenderPlaceholder = ( viewscale >= 3 - && allowSettingPixel + && !fetchingPixel && (hover || this.hover) && !isPotato ); const doRenderPotatoPlaceholder = ( viewscale >= 3 - && allowSettingPixel + && !fetchingPixel && (hover !== this.hover || this.forceNextRender || this.forceNextSubrender diff --git a/src/ui/Renderer3D.js b/src/ui/Renderer3D.js index 2f2cf86..9900476 100644 --- a/src/ui/Renderer3D.js +++ b/src/ui/Renderer3D.js @@ -20,8 +20,7 @@ import { setHover, selectColor, } from '../store/actions'; -import { tryPlacePixel } from './placePixel'; - +import pixelTransferController from './PixelTransferController'; const renderDistance = 150; @@ -398,8 +397,8 @@ class Renderer { store, } = this; const { - allowSettingPixel, - } = store.getState().user; + fetchingPixel, + } = store.getState().fetching; mouse.set( (clientX / innerWidth) * 2 - 1, @@ -414,7 +413,7 @@ class Renderer { .add(intersect.face.normal.multiplyScalar(0.5)) .floor() .addScalar(0.5); - if (!allowSettingPixel + if (fetchingPixel || target.clone().sub(camera.position).length() > 120) { rollOverMesh.position.y = -10; } else { @@ -442,8 +441,8 @@ class Renderer { store, } = this; const { - allowSettingPixel, - } = store.getState().user; + fetchingPixel, + } = store.getState().fetching; mouse.set(0, 0); raycaster.setFromCamera(mouse, camera); @@ -454,9 +453,9 @@ class Renderer { .add(intersect.face.normal.multiplyScalar(0.5)) .floor() .addScalar(0.5); - // TODO make rollOverMesh in a different color while allowSettingPixel false + // TODO make rollOverMesh in a different color while fetchingPixel // instead of hiding it.... we can now queue Voxels - if (!allowSettingPixel + if (fetchingPixel || target.clone().sub(camera.position).length() > 50) { rollOverMesh.position.y = -10; } else { @@ -481,9 +480,7 @@ class Renderer { const curColor = (chClr === 0) ? this.chunkLoader.getVoxel(x, y, z) : 0; const [i, j] = getChunkOfPixel(canvasSize, x, y, z); const offset = getOffsetOfPixel(canvasSize, x, y, z); - tryPlacePixel( - this, - store, + pixelTransferController.tryPlacePixel( i, j, offset, chClr, @@ -579,10 +576,12 @@ class Renderer { const state = this.store.getState(); const { - allowSettingPixel, isOnMobile, } = state.user; - if (!allowSettingPixel || isOnMobile) { + const { + fetchingPixel, + } = state.fetching; + if (fetchingPixel || isOnMobile) { return; } diff --git a/src/ui/placePixel.js b/src/ui/placePixel.js deleted file mode 100644 index 7ec34ba..0000000 --- a/src/ui/placePixel.js +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Place pixel via Websocket - * Always just one pixelrequest, queue additional requests to send later - * Pixels get predicted on the client and reset if server refused - * - * TODO move stuff out of here and to actions / middleware - * clientPredictions could be in rendererHook - * - * */ -import { t } from 'ttag'; -import { - requestPlaceTimeout, - pAlert, - storeReceivePixelReturn, - requestPlacePixels, -} from '../store/actions'; -import { - notify, -} from '../store/actions/thunks'; - -let pixelTimeout = null; -/* - * cache of pixels that still are to set - * [{i: i, j: j, pixels: [[offset, color],...]}, ...] - */ -let pixelQueue = []; -/* - * requests that got predicted on client and yet have to be - * received from the server - * [[i, j, offset, colorold, colornew], ...] - */ -let clientPredictions = []; -/* - * values of last request - * {i: i, j: j, pixels: [[offset, color], ...} - */ -let lastRequestValues = {}; - -/* - * request pixel placement from queue - */ -function requestFromQueue(store) { - if (!pixelQueue.length) { - pixelTimeout = null; - return; - } - - /* timeout to warn user when Websocket is dysfunctional */ - pixelTimeout = setTimeout(() => { - pixelQueue = []; - pixelTimeout = null; - store.dispatch(requestPlaceTimeout()); - store.dispatch(pAlert( - t`Error :(`, - t`Didn't get an answer from pixelplanet. Maybe try to refresh?`, - 'error', - )); - }, 15000); - - lastRequestValues = pixelQueue.shift(); - const { i, j, pixels } = lastRequestValues; - store.dispatch(requestPlacePixels(i, j, pixels)); -} - -/* - * got pixel update from websocket - */ -export function receivePixelUpdate( - renderer, - i, - j, - offset, - color, -) { - for (let p = 0; p < clientPredictions.length; p += 1) { - const predPxl = clientPredictions[p]; - if (predPxl[0] === i - && predPxl[1] === j - && predPxl[2] === offset - ) { - if (predPxl[4] === color) { - clientPredictions.splice(p, 1); - } - return; - } - } - renderer.renderPixel(i, j, offset, color, true); -} - -/* - * Revert predictions starting at given pixel - * @param i, j, offset data of the first pixel that got rejected - */ -function revertPredictionsAt( - renderer, - sI, - sJ, - sOffset, -) { - let p = 0; - while (p < clientPredictions.length) { - const predPxl = clientPredictions[p]; - if (predPxl[0] === sI - && predPxl[1] === sJ - && predPxl[2] === sOffset - ) { - break; - } - p += 1; - } - - if (p >= clientPredictions.length) { - clientPredictions = []; - return; - } - - while (p < clientPredictions.length) { - const [i, j, offset, color] = clientPredictions[p]; - renderer.renderPixel(i, j, offset, color, false); - p += 1; - } - - clientPredictions = []; -} - -/* - * try to place a pixel - */ -export function tryPlacePixel( - renderer, - store, - i, - j, - offset, - color, - curColor, -) { - renderer.renderPixel(i, j, offset, color, false); - clientPredictions.push([i, j, offset, curColor, color]); - - if (pixelQueue.length) { - const lastReq = pixelQueue[pixelQueue.length - 1]; - const { i: lastI, j: lastJ } = lastReq; - if (i === lastI && j === lastJ) { - /* append to last request in queue if same chunk */ - lastReq.pixels.push([offset, color]); - } - return; - } - - pixelQueue.push({ - i, - j, - pixels: [[offset, color]], - }); - - if (!pixelTimeout) { - requestFromQueue(store); - } -} - -/* - * got return from pixel request - */ -export function receivePixelReturn( - store, - renderer, - args, -) { - clearTimeout(pixelTimeout); - - store.dispatch(storeReceivePixelReturn(args)); - - const { - retCode, - coolDownSeconds, - pxlCnt, - } = args; - - if (coolDownSeconds) { - store.dispatch(notify(coolDownSeconds)); - } - - if (retCode) { - /* - * one or more pixels didn't get set, - * revert predictions and clean queue - */ - const { i, j, pixels } = lastRequestValues; - const [offset] = pixels[pxlCnt]; - revertPredictionsAt(renderer, i, j, offset); - pixelQueue = []; - } - - let errorTitle = null; - let msg = null; - let type = 'error'; - switch (retCode) { - case 0: - break; - case 1: - errorTitle = t`Invalid Canvas`; - msg = t`This canvas doesn't exist`; - break; - case 2: - errorTitle = t`Invalid Coordinates`; - msg = t`x out of bounds`; - break; - case 3: - errorTitle = t`Invalid Coordinates`; - msg = t`y out of bounds`; - break; - case 4: - errorTitle = t`Invalid Coordinates`; - msg = t`z out of bounds`; - break; - case 5: - errorTitle = t`Wrong Color`; - msg = t`Invalid color selected`; - break; - case 6: - errorTitle = t`Just for registered Users`; - msg = t`You have to be logged in to place on this canvas`; - break; - case 7: - errorTitle = t`Place more :)`; - // eslint-disable-next-line max-len - msg = t`You can not access this canvas yet. You need to place more pixels`; - break; - case 8: - store.dispatch(notify(t`Pixel protected!`)); - break; - case 9: - // pixestack used up - break; - case 10: - errorTitle = 'Captcha'; - msg = t`Please prove that you are human`; - type = 'captcha'; - break; - case 11: - errorTitle = t`No Proxies Allowed :(`; - msg = t`You are using a Proxy.`; - break; - case 12: - errorTitle = t`Not allowed`; - msg = t`Just the Top10 of yesterday can place here`; - break; - case 13: - errorTitle = t`You are weird`; - // eslint-disable-next-line max-len - msg = t`Server got confused by your pixels. Are you playing on multiple devices?`; - break; - case 14: - errorTitle = t`Banned`; - type = 'ban'; - break; - case 15: - errorTitle = t`Range Banned`; - msg = t`Your Internet Provider is banned from playing this game`; - break; - default: - errorTitle = t`Weird`; - msg = t`Couldn't set Pixel`; - } - - if (msg || errorTitle) { - store.dispatch(pAlert( - (errorTitle || t`Error ${retCode}`), - msg, - type, - )); - } - - requestFromQueue(store); -} -