Allow translating server messages
This commit is contained in:
parent
3412f31250
commit
2858626600
6 changed files with 358 additions and 116 deletions
13
go.mod
13
go.mod
|
@ -7,9 +7,11 @@ require (
|
|||
github.com/alexedwards/argon2id v1.0.0
|
||||
github.com/gobwas/ws v1.3.2
|
||||
github.com/gorilla/mux v1.8.1
|
||||
github.com/jackc/pgx/v5 v5.5.3
|
||||
github.com/jackc/pgx/v5 v5.5.5
|
||||
github.com/jlouis/glicko2 v1.0.0
|
||||
github.com/leonelquinteros/gotext v1.5.3-0.20231003122255-12a99145a351
|
||||
github.com/matcornic/hermes/v2 v2.1.0
|
||||
golang.org/x/text v0.14.0
|
||||
)
|
||||
|
||||
require (
|
||||
|
@ -17,7 +19,7 @@ require (
|
|||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/Masterminds/semver v1.5.0 // indirect
|
||||
github.com/Masterminds/sprig v2.22.0+incompatible // indirect
|
||||
github.com/PuerkitoBio/goquery v1.8.1 // indirect
|
||||
github.com/PuerkitoBio/goquery v1.9.1 // indirect
|
||||
github.com/andybalholm/cascadia v1.3.2 // indirect
|
||||
github.com/gobwas/httphead v0.1.0 // indirect
|
||||
github.com/gobwas/pool v0.2.1 // indirect
|
||||
|
@ -37,8 +39,7 @@ require (
|
|||
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect
|
||||
github.com/vanng822/css v1.0.1 // indirect
|
||||
github.com/vanng822/go-premailer v1.20.2 // indirect
|
||||
golang.org/x/crypto v0.19.0 // indirect
|
||||
golang.org/x/net v0.21.0 // indirect
|
||||
golang.org/x/sys v0.17.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/crypto v0.21.0 // indirect
|
||||
golang.org/x/net v0.22.0 // indirect
|
||||
golang.org/x/sys v0.18.0 // indirect
|
||||
)
|
||||
|
|
30
go.sum
30
go.sum
|
@ -12,13 +12,12 @@ github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZC
|
|||
github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o=
|
||||
github.com/PuerkitoBio/goquery v1.5.0/go.mod h1:qD2PgZ9lccMbQlc7eEOjaeRlFQON7xY8kdmcsrnKqMg=
|
||||
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
|
||||
github.com/PuerkitoBio/goquery v1.8.1 h1:uQxhNlArOIdbrH1tr0UXwdVFgDcZDrZVdcpygAcwmWM=
|
||||
github.com/PuerkitoBio/goquery v1.8.1/go.mod h1:Q8ICL1kNUJ2sXGoAhPGUdYDJvgQgHzJsnnd3H7Ho5jQ=
|
||||
github.com/PuerkitoBio/goquery v1.9.1 h1:mTL6XjbJTZdpfL+Gwl5U2h1l9yEkJjhmlTeV9VPW7UI=
|
||||
github.com/PuerkitoBio/goquery v1.9.1/go.mod h1:cW1n6TmIMDoORQU5IU/P1T3tGFunOeXEpGP2WHRwkbY=
|
||||
github.com/alexedwards/argon2id v1.0.0 h1:wJzDx66hqWX7siL/SRUmgz3F8YMrd/nfX/xHHcQQP0w=
|
||||
github.com/alexedwards/argon2id v1.0.0/go.mod h1:tYKkqIjzXvZdzPvADMWOEZ+l6+BD6CtBXMj5fnJppiw=
|
||||
github.com/andybalholm/cascadia v1.0.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
||||
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
||||
github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA=
|
||||
github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss=
|
||||
github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU=
|
||||
github.com/aokoli/goutils v1.0.1/go.mod h1:SijmP0QR8LtwsmDs8Yii5Z/S4trXFGFC2oO5g9DP+DQ=
|
||||
|
@ -51,8 +50,8 @@ github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsI
|
|||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 h1:L0QtFUgDarD7Fpv9jeVMgy/+Ec0mtnmYuImjTz6dtDA=
|
||||
github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||
github.com/jackc/pgx/v5 v5.5.3 h1:Ces6/M3wbDXYpM8JyyPD57ivTtJACFZJd885pdIaV2s=
|
||||
github.com/jackc/pgx/v5 v5.5.3/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A=
|
||||
github.com/jackc/pgx/v5 v5.5.5 h1:amBjrZVmksIdNjxGW/IiIMzxMKZFelXbUoPNb+8sjQw=
|
||||
github.com/jackc/pgx/v5 v5.5.5/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A=
|
||||
github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
|
||||
github.com/jaytaylor/html2text v0.0.0-20180606194806-57d518f124b0/go.mod h1:CVKlgaMiht+LXvHG173ujK6JUhZXKb2u/BQtjPDIvyk=
|
||||
github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056 h1:iCHtR9CQyktQ5+f3dMVZfwD2KWJUgm7M0gdL9NGr8KA=
|
||||
|
@ -62,6 +61,10 @@ github.com/jlouis/glicko2 v1.0.0/go.mod h1:5dzlxjhVPPLk+wiUwwF2oVyDwsNXMgnw7WrLR
|
|||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/leonelquinteros/gotext v1.5.2 h1:T2y6ebHli+rMBCjcJlHTXyUrgXqsKBhl/ormgvt7lPo=
|
||||
github.com/leonelquinteros/gotext v1.5.2/go.mod h1:AT4NpQrOmyj1L/+hLja6aR0lk81yYYL4ePnj2kp7d6M=
|
||||
github.com/leonelquinteros/gotext v1.5.3-0.20231003122255-12a99145a351 h1:Rk+RkO4xEZMkEok69CbeA6cgXKyVCsgF3qGGGR46pd8=
|
||||
github.com/leonelquinteros/gotext v1.5.3-0.20231003122255-12a99145a351/go.mod h1:qQRISjoonXYFdRGrTG1LARQ38Gpibad0IPeB4hpvyyM=
|
||||
github.com/matcornic/hermes/v2 v2.1.0 h1:9TDYFBPFv6mcXanaDmRDEp/RTWj0dTTi+LpFnnnfNWc=
|
||||
github.com/matcornic/hermes/v2 v2.1.0/go.mod h1:2+ziJeoyRfaLiATIL8VZ7f9hpzH4oDHqTmn0bhrsgVI=
|
||||
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
|
@ -106,8 +109,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
|||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||
golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
|
||||
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
|
@ -117,14 +120,12 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
|
|||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc=
|
||||
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||
|
@ -134,7 +135,6 @@ golang.org/x/sys v0.0.0-20190225065934-cc5685c2db12/go.mod h1:STP8DvDyc/dI5b8T5h
|
|||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
|
@ -143,8 +143,8 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
|
||||
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
|
@ -153,8 +153,8 @@ golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
|||
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
|
|
|
@ -71,6 +71,7 @@ type serverClient struct {
|
|||
id int
|
||||
json bool
|
||||
name []byte
|
||||
language string
|
||||
account *account
|
||||
accountID int
|
||||
connected int64
|
||||
|
|
176
pkg/server/locales/bgammon.pot
Normal file
176
pkg/server/locales/bgammon.pot
Normal file
|
@ -0,0 +1,176 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: \n"
|
||||
"X-Generator: xgotext\n"
|
||||
|
||||
msgid "%s accepted double."
|
||||
msgstr ""
|
||||
|
||||
msgid "%s declined double offer."
|
||||
msgstr ""
|
||||
|
||||
msgid "%s offers a double (%d points)."
|
||||
msgstr ""
|
||||
|
||||
msgid "Accepted double."
|
||||
msgstr ""
|
||||
|
||||
msgid "Choose which doubles you want for your acey-deucey."
|
||||
msgstr ""
|
||||
|
||||
msgid "Command ignored: You are spectating this match."
|
||||
msgstr ""
|
||||
|
||||
msgid "Connect with other players and stay up to date on the latest changes. Visit %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Created match: %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Declined double offer"
|
||||
msgstr ""
|
||||
|
||||
msgid "Double offered to opponent (%d points)."
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to change password."
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to change password: incorrect existing password."
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to change password: you are logged in as a guest."
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to create match: Please leave the match you are in before creating another."
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to log in: %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Illegal move."
|
||||
msgstr ""
|
||||
|
||||
msgid "Invalid password."
|
||||
msgstr ""
|
||||
|
||||
msgid "Invalid replay ID provided."
|
||||
msgstr ""
|
||||
|
||||
msgid "Invalid username: must contain at least one non-numeric character."
|
||||
msgstr ""
|
||||
|
||||
msgid "Invalid username: must contain only letters, numbers and underscores."
|
||||
msgstr ""
|
||||
|
||||
msgid "It is not your turn to move."
|
||||
msgstr ""
|
||||
|
||||
msgid "It is not your turn to roll."
|
||||
msgstr ""
|
||||
|
||||
msgid "It is not your turn."
|
||||
msgstr ""
|
||||
|
||||
msgid "Joined match: %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Match not found."
|
||||
msgstr ""
|
||||
|
||||
msgid "Message not sent: There is no one else in the match."
|
||||
msgstr ""
|
||||
|
||||
msgid "Message not sent: You are not currently in a match."
|
||||
msgstr ""
|
||||
|
||||
msgid "No account was found with the provided username and password. To log in as a guest, do not enter a password."
|
||||
msgstr ""
|
||||
|
||||
msgid "No replay was recorded for that game."
|
||||
msgstr ""
|
||||
|
||||
msgid "Password changed successfully."
|
||||
msgstr ""
|
||||
|
||||
msgid "Please leave the match you are in before joining another."
|
||||
msgstr ""
|
||||
|
||||
msgid "Rejoined match: %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Rematch offer sent."
|
||||
msgstr ""
|
||||
|
||||
msgid "Server error"
|
||||
msgstr ""
|
||||
|
||||
msgid "That username is already in use."
|
||||
msgstr ""
|
||||
|
||||
msgid "The following legal moves are available: %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "The match you are in is still in progress."
|
||||
msgstr ""
|
||||
|
||||
msgid "Unknown command: %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Waiting for response from opponent."
|
||||
msgstr ""
|
||||
|
||||
msgid "You are not allowed to use that command."
|
||||
msgstr ""
|
||||
|
||||
msgid "You are not currently in a match."
|
||||
msgstr ""
|
||||
|
||||
msgid "You are spectating this match. Chat messages are not relayed."
|
||||
msgstr ""
|
||||
|
||||
msgid "You do not currently hold the doubling cube."
|
||||
msgstr ""
|
||||
|
||||
msgid "You have already requested a rematch."
|
||||
msgstr ""
|
||||
|
||||
msgid "You may not accept the double until your opponent rejoins the match."
|
||||
msgstr ""
|
||||
|
||||
msgid "You may not double at this time."
|
||||
msgstr ""
|
||||
|
||||
msgid "You may not double until your opponent rejoins the match."
|
||||
msgstr ""
|
||||
|
||||
msgid "You may not move until your opponent rejoins the match."
|
||||
msgstr ""
|
||||
|
||||
msgid "You may not resign at this time."
|
||||
msgstr ""
|
||||
|
||||
msgid "You may not resign until your opponent rejoins the match."
|
||||
msgstr ""
|
||||
|
||||
msgid "You may not roll until your opponent rejoins the match."
|
||||
msgstr ""
|
||||
|
||||
msgid "You must login before using other commands."
|
||||
msgstr ""
|
||||
|
||||
msgid "You must roll first."
|
||||
msgstr ""
|
||||
|
||||
msgid "You must wait until your opponent rejoins the match before continuing the game."
|
||||
msgstr ""
|
||||
|
||||
msgid "Your opponent left the match."
|
||||
msgstr ""
|
||||
|
||||
msgid "Your opponent would like to play again. Type %s to accept."
|
||||
msgstr ""
|
|
@ -1,9 +1,12 @@
|
|||
package server
|
||||
|
||||
//go:generate xgotext -no-locations -default bgammon -in . -out locales
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"embed"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"log"
|
||||
|
@ -19,6 +22,8 @@ import (
|
|||
"time"
|
||||
|
||||
"code.rocket9labs.com/tslocum/bgammon"
|
||||
"github.com/leonelquinteros/gotext"
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
const clientTimeout = 40 * time.Second
|
||||
|
@ -33,6 +38,15 @@ var (
|
|||
alphaNumericUnderscore = regexp.MustCompile(`^[A-Za-z0-9_]+$`)
|
||||
)
|
||||
|
||||
//go:embed locales
|
||||
var assetFS embed.FS
|
||||
|
||||
var englishIdentifier = []byte("en")
|
||||
|
||||
func init() {
|
||||
gotext.SetDomain("bgammon-en")
|
||||
}
|
||||
|
||||
type serverCommand struct {
|
||||
client *serverClient
|
||||
command []byte
|
||||
|
@ -66,7 +80,9 @@ type server struct {
|
|||
passwordSalt string
|
||||
resetSalt string
|
||||
|
||||
tz *time.Location
|
||||
tz *time.Location
|
||||
languageTags []language.Tag
|
||||
languageNames [][]byte
|
||||
|
||||
relayChat bool // Chats are not relayed normally. This option is only used by local servers.
|
||||
verbose bool
|
||||
|
@ -85,6 +101,7 @@ func NewServer(tz string, dataSource string, mailServer string, passwordSalt str
|
|||
relayChat: relayChat,
|
||||
verbose: verbose,
|
||||
}
|
||||
s.loadLocales()
|
||||
|
||||
if tz != "" {
|
||||
var err error
|
||||
|
@ -114,25 +131,6 @@ func NewServer(tz string, dataSource string, mailServer string, passwordSalt str
|
|||
|
||||
allowDebugCommands = allowDebug
|
||||
|
||||
/*gm := bgammon.NewGame(bgammon.VariantBackgammon)
|
||||
gm.Turn = 1
|
||||
gm.Roll1 = 2
|
||||
gm.Roll2 = 3
|
||||
log.Println(gm.MayBearOff(1, false))
|
||||
gm.Player1.Entered = true
|
||||
gm.Player2.Entered = true
|
||||
log.Println(gm.Board)
|
||||
//ok, expanded := gm.AddMoves([][]int8{{3, 1}}, false)
|
||||
//log.Println(ok, expanded, "!")
|
||||
log.Println(gm.MayBearOff(1, false))
|
||||
gs := &bgammon.GameState{
|
||||
Game: gm,
|
||||
PlayerNumber: 1,
|
||||
Available: gm.LegalMoves(false),
|
||||
}
|
||||
log.Printf("%+v", gs)
|
||||
os.Exit(0)*/
|
||||
|
||||
go s.handleNewGameIDs()
|
||||
go s.handleNewClientIDs()
|
||||
go s.handleCommands()
|
||||
|
@ -140,6 +138,57 @@ func NewServer(tz string, dataSource string, mailServer string, passwordSalt str
|
|||
return s
|
||||
}
|
||||
|
||||
func (s *server) loadLocales() {
|
||||
entries, err := assetFS.ReadDir("locales")
|
||||
if err != nil {
|
||||
log.Fatalf("failed to list files in locales directory: %s", err)
|
||||
}
|
||||
|
||||
var availableTags = []language.Tag{
|
||||
language.MustParse("en_US"),
|
||||
}
|
||||
var availableNames = [][]byte{
|
||||
[]byte("en"),
|
||||
}
|
||||
for _, entry := range entries {
|
||||
if !entry.IsDir() {
|
||||
continue
|
||||
}
|
||||
availableTags = append(availableTags, language.MustParse(entry.Name()))
|
||||
availableNames = append(availableNames, []byte(entry.Name()))
|
||||
|
||||
b, err := assetFS.ReadFile(fmt.Sprintf("locales/%s/%s.po", entry.Name(), entry.Name()))
|
||||
if err != nil {
|
||||
log.Fatalf("failed to read locale %s: %s", entry.Name(), err)
|
||||
}
|
||||
|
||||
po := gotext.NewPo()
|
||||
po.Parse(b)
|
||||
gotext.GetStorage().AddTranslator(fmt.Sprintf("bgammon-%s", entry.Name()), po)
|
||||
}
|
||||
s.languageTags = availableTags
|
||||
s.languageNames = availableNames
|
||||
}
|
||||
|
||||
func (s *server) matchLanguage(identifier []byte) []byte {
|
||||
if len(identifier) == 0 {
|
||||
return englishIdentifier
|
||||
}
|
||||
|
||||
tag, err := language.Parse(string(identifier))
|
||||
if err != nil {
|
||||
return englishIdentifier
|
||||
}
|
||||
var preferred = []language.Tag{tag}
|
||||
|
||||
useLanguage, index, _ := language.NewMatcher(s.languageTags).Match(preferred...)
|
||||
useLanguageCode := useLanguage.String()
|
||||
if index < 0 || useLanguageCode == "" || strings.HasPrefix(useLanguageCode, "en") {
|
||||
return englishIdentifier
|
||||
}
|
||||
return s.languageNames[index]
|
||||
}
|
||||
|
||||
func (s *server) ListenLocal() chan net.Conn {
|
||||
conns := make(chan net.Conn)
|
||||
go s.handleLocal(conns)
|
||||
|
@ -194,6 +243,7 @@ func (s *server) handleWebSocket(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
c := &serverClient{
|
||||
id: <-s.newClientIDs,
|
||||
language: "bgammon-en",
|
||||
accountID: -1,
|
||||
connected: now,
|
||||
active: now,
|
||||
|
@ -341,6 +391,7 @@ func (s *server) handleConnection(conn net.Conn) {
|
|||
|
||||
c := &serverClient{
|
||||
id: <-s.newClientIDs,
|
||||
language: "bgammon-en",
|
||||
accountID: -1,
|
||||
connected: now,
|
||||
active: now,
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"time"
|
||||
|
||||
"code.rocket9labs.com/tslocum/bgammon"
|
||||
"github.com/leonelquinteros/gotext"
|
||||
)
|
||||
|
||||
func (s *server) handleCommands() {
|
||||
|
@ -77,6 +78,10 @@ COMMANDS:
|
|||
sendUsage()
|
||||
continue
|
||||
}
|
||||
slashIndex := bytes.IndexRune(params[0], '/')
|
||||
if slashIndex != -1 {
|
||||
cmd.client.language = "bgammon-" + string(s.matchLanguage(params[0][slashIndex+1:]))
|
||||
}
|
||||
email = params[1]
|
||||
username = params[2]
|
||||
password = bytes.Join(params[3:], []byte("_"))
|
||||
|
@ -109,8 +114,14 @@ COMMANDS:
|
|||
|
||||
readUsername := func() bool {
|
||||
if cmd.client.json {
|
||||
if len(params) > 1 {
|
||||
username = params[1]
|
||||
if len(params) > 0 {
|
||||
slashIndex := bytes.IndexRune(params[0], '/')
|
||||
if slashIndex != -1 {
|
||||
cmd.client.language = "bgammon-" + string(s.matchLanguage(params[0][slashIndex+1:]))
|
||||
}
|
||||
if len(params) > 1 {
|
||||
username = params[1]
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if len(params) > 0 {
|
||||
|
@ -121,14 +132,16 @@ COMMANDS:
|
|||
username = s.randomUsername()
|
||||
randomUsername = true
|
||||
} else if !alphaNumericUnderscore.Match(username) {
|
||||
cmd.client.Terminate("Invalid username: must contain only letters, numbers and underscores.")
|
||||
cmd.client.Terminate(gotext.GetD(cmd.client.language, "Invalid username: must contain only letters, numbers and underscores."))
|
||||
return false
|
||||
}
|
||||
if onlyNumbers.Match(username) {
|
||||
cmd.client.Terminate("Invalid username: must contain at least one non-numeric character.")
|
||||
log.Println(cmd.client.language)
|
||||
log.Println("!")
|
||||
cmd.client.Terminate(gotext.GetD(cmd.client.language, "Invalid username: must contain at least one non-numeric character."))
|
||||
return false
|
||||
} else if s.clientByUsername(username) != nil || s.clientByUsername(append([]byte("Guest_"), username...)) != nil || (!randomUsername && !s.nameAllowed(username)) {
|
||||
cmd.client.Terminate("That username is already in use.")
|
||||
cmd.client.Terminate(gotext.GetD(cmd.client.language, "That username is already in use."))
|
||||
return false
|
||||
}
|
||||
return true
|
||||
|
@ -147,10 +160,10 @@ COMMANDS:
|
|||
if len(password) > 0 {
|
||||
a, err := loginAccount(s.passwordSalt, username, password)
|
||||
if err != nil {
|
||||
cmd.client.Terminate(fmt.Sprintf("Failed to log in: %s", err))
|
||||
cmd.client.Terminate(fmt.Sprintf(gotext.GetD(cmd.client.language, "Failed to log in: %s"), err))
|
||||
continue
|
||||
} else if a == nil {
|
||||
cmd.client.Terminate("No account was found with the provided username and password. To log in as a guest, do not enter a password.")
|
||||
cmd.client.Terminate(gotext.GetD(cmd.client.language, "No account was found with the provided username and password. To log in as a guest, do not enter a password."))
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -161,7 +174,7 @@ COMMANDS:
|
|||
name = a.username
|
||||
}
|
||||
if s.clientByUsername(name) != nil {
|
||||
cmd.client.Terminate("That username is already in use.")
|
||||
cmd.client.Terminate(gotext.GetD(cmd.client.language, "That username is already in use."))
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -201,7 +214,7 @@ COMMANDS:
|
|||
}
|
||||
|
||||
// Send message of the day.
|
||||
cmd.client.sendNotice("Connect with other players and stay up to date on the latest changes. Visit bgammon.org/community")
|
||||
cmd.client.sendNotice(fmt.Sprintf(gotext.GetD(cmd.client.language, "Connect with other players and stay up to date on the latest changes. Visit %s"), "bgammon.org/community"))
|
||||
|
||||
// Rejoin match in progress.
|
||||
s.gamesLock.RLock()
|
||||
|
@ -218,14 +231,14 @@ COMMANDS:
|
|||
}
|
||||
if rejoin {
|
||||
g.addClient(cmd.client)
|
||||
cmd.client.sendNotice(fmt.Sprintf("Rejoined match: %s", g.name))
|
||||
cmd.client.sendNotice(fmt.Sprintf(gotext.GetD(cmd.client.language, "Rejoined match: %s"), g.name))
|
||||
}
|
||||
}
|
||||
s.gamesLock.RUnlock()
|
||||
continue
|
||||
}
|
||||
|
||||
cmd.client.Terminate("You must login before using other commands.")
|
||||
cmd.client.Terminate(gotext.GetD(cmd.client.language, "You must login before using other commands."))
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -235,7 +248,7 @@ COMMANDS:
|
|||
case bgammon.CommandHelp, "h", bgammon.CommandJSON, bgammon.CommandList, "ls", bgammon.CommandBoard, "b", bgammon.CommandLeave, "l", bgammon.CommandReplay, bgammon.CommandSet, bgammon.CommandDisconnect, bgammon.CommandPong:
|
||||
// These commands are allowed to be used by spectators.
|
||||
default:
|
||||
cmd.client.sendNotice("Command ignored: You are spectating this match.")
|
||||
cmd.client.sendNotice(gotext.GetD(cmd.client.language, "Command ignored: You are spectating this match."))
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
@ -271,12 +284,12 @@ COMMANDS:
|
|||
continue
|
||||
}
|
||||
if clientGame == nil {
|
||||
cmd.client.sendNotice("Message not sent: You are not currently in a match.")
|
||||
cmd.client.sendNotice(gotext.GetD(cmd.client.language, "Message not sent: You are not currently in a match."))
|
||||
continue
|
||||
}
|
||||
opponent := clientGame.opponent(cmd.client)
|
||||
if opponent == nil {
|
||||
cmd.client.sendNotice("Message not sent: There is no one else in the match.")
|
||||
cmd.client.sendNotice(gotext.GetD(cmd.client.language, "Message not sent: There is no one else in the match."))
|
||||
continue
|
||||
}
|
||||
ev := &bgammon.EventSay{
|
||||
|
@ -305,7 +318,7 @@ COMMANDS:
|
|||
cmd.client.sendEvent(ev)
|
||||
case bgammon.CommandCreate, "c":
|
||||
if clientGame != nil {
|
||||
cmd.client.sendNotice("Failed to create match: Please leave the match you are in before creating another.")
|
||||
cmd.client.sendNotice(gotext.GetD(cmd.client.language, "Failed to create match: Please leave the match you are in before creating another."))
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -387,7 +400,7 @@ COMMANDS:
|
|||
s.games = append(s.games, g)
|
||||
s.gamesLock.Unlock()
|
||||
|
||||
cmd.client.sendNotice(fmt.Sprintf("Created match: %s", g.name))
|
||||
cmd.client.sendNotice(fmt.Sprintf(gotext.GetD(cmd.client.language, "Created match: %s"), g.name))
|
||||
|
||||
if len(g.password) == 0 {
|
||||
cmd.client.sendNotice("Note: Please be patient as you wait for another player to join the match. A chime will sound when another player joins. While you wait, join the bgammon.org community via Discord, Matrix or IRC at bgammon.org/community")
|
||||
|
@ -395,7 +408,7 @@ COMMANDS:
|
|||
case bgammon.CommandJoin, "j":
|
||||
if clientGame != nil {
|
||||
cmd.client.sendEvent(&bgammon.EventFailedJoin{
|
||||
Reason: "Please leave the match you are in before joining another.",
|
||||
Reason: gotext.GetD(cmd.client.language, "Please leave the match you are in before joining another."),
|
||||
})
|
||||
continue
|
||||
}
|
||||
|
@ -436,7 +449,7 @@ COMMANDS:
|
|||
|
||||
if joinGameID == 0 {
|
||||
cmd.client.sendEvent(&bgammon.EventFailedJoin{
|
||||
Reason: "Match not found.",
|
||||
Reason: gotext.GetD(cmd.client.language, "Match not found."),
|
||||
})
|
||||
continue
|
||||
}
|
||||
|
@ -451,7 +464,7 @@ COMMANDS:
|
|||
providedPassword := bytes.ReplaceAll(bytes.Join(params[1:], []byte(" ")), []byte("_"), []byte(" "))
|
||||
if len(g.password) != 0 && (len(params) < 2 || !bytes.Equal(g.password, providedPassword)) {
|
||||
cmd.client.sendEvent(&bgammon.EventFailedJoin{
|
||||
Reason: "Invalid password.",
|
||||
Reason: gotext.GetD(cmd.client.language, "Invalid password."),
|
||||
})
|
||||
s.gamesLock.Unlock()
|
||||
continue COMMANDS
|
||||
|
@ -466,9 +479,9 @@ COMMANDS:
|
|||
|
||||
spectator := g.addClient(cmd.client)
|
||||
s.gamesLock.Unlock()
|
||||
cmd.client.sendNotice(fmt.Sprintf("Joined match: %s", g.name))
|
||||
cmd.client.sendNotice(fmt.Sprintf(gotext.GetD(cmd.client.language, "Joined match: %s"), g.name))
|
||||
if spectator {
|
||||
cmd.client.sendNotice("You are spectating this match. Chat messages are not relayed.")
|
||||
cmd.client.sendNotice(gotext.GetD(cmd.client.language, "You are spectating this match. Chat messages are not relayed."))
|
||||
}
|
||||
continue COMMANDS
|
||||
}
|
||||
|
@ -476,12 +489,12 @@ COMMANDS:
|
|||
s.gamesLock.Unlock()
|
||||
|
||||
cmd.client.sendEvent(&bgammon.EventFailedJoin{
|
||||
Reason: "Match not found.",
|
||||
Reason: gotext.GetD(cmd.client.language, "Match not found."),
|
||||
})
|
||||
case bgammon.CommandLeave, "l":
|
||||
if clientGame == nil {
|
||||
cmd.client.sendEvent(&bgammon.EventFailedLeave{
|
||||
Reason: "You are not currently in a match.",
|
||||
Reason: gotext.GetD(cmd.client.language, "You are not currently in a match."),
|
||||
})
|
||||
continue
|
||||
}
|
||||
|
@ -495,14 +508,14 @@ COMMANDS:
|
|||
clientGame.removeClient(cmd.client)
|
||||
case bgammon.CommandDouble, "d":
|
||||
if clientGame == nil {
|
||||
cmd.client.sendNotice("You are not currently in a match.")
|
||||
cmd.client.sendNotice(gotext.GetD(cmd.client.language, "You are not currently in a match."))
|
||||
continue
|
||||
} else if clientGame.Winner != 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
if clientGame.Turn != cmd.client.playerNumber {
|
||||
cmd.client.sendNotice("It is not your turn.")
|
||||
cmd.client.sendNotice(gotext.GetD(cmd.client.language, "It is not your turn."))
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -512,26 +525,26 @@ COMMANDS:
|
|||
Available: clientGame.LegalMoves(false),
|
||||
}
|
||||
if !gameState.MayDouble() {
|
||||
cmd.client.sendNotice("You may not double at this time.")
|
||||
cmd.client.sendNotice(gotext.GetD(cmd.client.language, "You may not double at this time."))
|
||||
continue
|
||||
}
|
||||
|
||||
if clientGame.DoublePlayer != 0 && clientGame.DoublePlayer != cmd.client.playerNumber {
|
||||
cmd.client.sendNotice("You do not currently hold the doubling cube.")
|
||||
cmd.client.sendNotice(gotext.GetD(cmd.client.language, "You do not currently hold the doubling cube."))
|
||||
continue
|
||||
}
|
||||
|
||||
opponent := clientGame.opponent(cmd.client)
|
||||
if opponent == nil {
|
||||
cmd.client.sendNotice("You may not double until your opponent rejoins the match.")
|
||||
cmd.client.sendNotice(gotext.GetD(cmd.client.language, "You may not double until your opponent rejoins the match."))
|
||||
continue
|
||||
}
|
||||
|
||||
clientGame.DoubleOffered = true
|
||||
clientGame.NextPartialTurn(opponent.playerNumber)
|
||||
|
||||
cmd.client.sendNotice(fmt.Sprintf("Double offered to opponent (%d points).", clientGame.DoubleValue*2))
|
||||
clientGame.opponent(cmd.client).sendNotice(fmt.Sprintf("%s offers a double (%d points).", cmd.client.name, clientGame.DoubleValue*2))
|
||||
cmd.client.sendNotice(fmt.Sprintf(gotext.GetD(cmd.client.language, "Double offered to opponent (%d points)."), clientGame.DoubleValue*2))
|
||||
clientGame.opponent(cmd.client).sendNotice(fmt.Sprintf(gotext.GetD(clientGame.opponent(cmd.client).language, "%s offers a double (%d points)."), cmd.client.name, clientGame.DoubleValue*2))
|
||||
|
||||
clientGame.eachClient(func(client *serverClient) {
|
||||
if client.json {
|
||||
|
@ -540,7 +553,7 @@ COMMANDS:
|
|||
})
|
||||
case bgammon.CommandResign:
|
||||
if clientGame == nil {
|
||||
cmd.client.sendNotice("You are not currently in a match.")
|
||||
cmd.client.sendNotice(gotext.GetD(cmd.client.language, "You are not currently in a match."))
|
||||
continue
|
||||
} else if clientGame.Winner != 0 {
|
||||
continue
|
||||
|
@ -552,20 +565,20 @@ COMMANDS:
|
|||
Available: clientGame.LegalMoves(false),
|
||||
}
|
||||
if !gameState.MayResign() {
|
||||
cmd.client.sendNotice("You may not resign at this time.")
|
||||
cmd.client.sendNotice(gotext.GetD(cmd.client.language, "You may not resign at this time."))
|
||||
continue
|
||||
}
|
||||
|
||||
opponent := clientGame.opponent(cmd.client)
|
||||
if opponent == nil {
|
||||
cmd.client.sendNotice("You may not resign until your opponent rejoins the match.")
|
||||
cmd.client.sendNotice(gotext.GetD(cmd.client.language, "You may not resign until your opponent rejoins the match."))
|
||||
continue
|
||||
}
|
||||
|
||||
clientGame.NextPartialTurn(opponent.playerNumber)
|
||||
|
||||
cmd.client.sendNotice("Declined double offer")
|
||||
clientGame.opponent(cmd.client).sendNotice(fmt.Sprintf("%s declined double offer.", cmd.client.name))
|
||||
cmd.client.sendNotice(gotext.GetD(cmd.client.language, "Declined double offer"))
|
||||
clientGame.opponent(cmd.client).sendNotice(fmt.Sprintf(gotext.GetD(clientGame.opponent(cmd.client).language, "%s declined double offer."), cmd.client.name))
|
||||
|
||||
clientGame.replay = append([][]byte{[]byte(fmt.Sprintf("i %d %s %s %d %d %d %d %d %d", clientGame.Started.Unix(), clientGame.Player1.Name, clientGame.Player2.Name, clientGame.Points, clientGame.Player1.Points, clientGame.Player2.Points, clientGame.Winner, clientGame.DoubleValue, clientGame.Variant))}, clientGame.replay...)
|
||||
|
||||
|
@ -628,7 +641,7 @@ COMMANDS:
|
|||
case bgammon.CommandRoll, "r":
|
||||
if clientGame == nil {
|
||||
cmd.client.sendEvent(&bgammon.EventFailedRoll{
|
||||
Reason: "You are not currently in a match.",
|
||||
Reason: gotext.GetD(cmd.client.language, "You are not currently in a match."),
|
||||
})
|
||||
continue
|
||||
} else if clientGame.Winner != 0 {
|
||||
|
@ -638,14 +651,14 @@ COMMANDS:
|
|||
opponent := clientGame.opponent(cmd.client)
|
||||
if opponent == nil {
|
||||
cmd.client.sendEvent(&bgammon.EventFailedRoll{
|
||||
Reason: "You may not roll until your opponent rejoins the match.",
|
||||
Reason: gotext.GetD(cmd.client.language, "You may not roll until your opponent rejoins the match."),
|
||||
})
|
||||
continue
|
||||
}
|
||||
|
||||
if !clientGame.roll(cmd.client.playerNumber) {
|
||||
cmd.client.sendEvent(&bgammon.EventFailedRoll{
|
||||
Reason: "It is not your turn to roll.",
|
||||
Reason: gotext.GetD(cmd.client.language, "It is not your turn to roll."),
|
||||
})
|
||||
continue
|
||||
}
|
||||
|
@ -766,7 +779,7 @@ COMMANDS:
|
|||
case bgammon.CommandMove, "m", "mv":
|
||||
if clientGame == nil {
|
||||
cmd.client.sendEvent(&bgammon.EventFailedMove{
|
||||
Reason: "You are not currently in a match.",
|
||||
Reason: gotext.GetD(cmd.client.language, "You are not currently in a match."),
|
||||
})
|
||||
continue
|
||||
} else if clientGame.Winner != 0 {
|
||||
|
@ -776,7 +789,7 @@ COMMANDS:
|
|||
|
||||
if clientGame.Turn != cmd.client.playerNumber {
|
||||
cmd.client.sendEvent(&bgammon.EventFailedMove{
|
||||
Reason: "It is not your turn to move.",
|
||||
Reason: gotext.GetD(cmd.client.language, "It is not your turn to move."),
|
||||
})
|
||||
continue
|
||||
}
|
||||
|
@ -784,7 +797,7 @@ COMMANDS:
|
|||
opponent := clientGame.opponent(cmd.client)
|
||||
if opponent == nil {
|
||||
cmd.client.sendEvent(&bgammon.EventFailedMove{
|
||||
Reason: "You may not move until your opponent rejoins the match.",
|
||||
Reason: gotext.GetD(cmd.client.language, "You may not move until your opponent rejoins the match."),
|
||||
})
|
||||
continue
|
||||
}
|
||||
|
@ -821,7 +834,7 @@ COMMANDS:
|
|||
cmd.client.sendEvent(&bgammon.EventFailedMove{
|
||||
From: from,
|
||||
To: to,
|
||||
Reason: "Illegal move.",
|
||||
Reason: gotext.GetD(cmd.client.language, "Illegal move."),
|
||||
})
|
||||
continue COMMANDS
|
||||
}
|
||||
|
@ -835,7 +848,7 @@ COMMANDS:
|
|||
cmd.client.sendEvent(&bgammon.EventFailedMove{
|
||||
From: 0,
|
||||
To: 0,
|
||||
Reason: "Illegal move.",
|
||||
Reason: gotext.GetD(cmd.client.language, "Illegal move."),
|
||||
})
|
||||
continue
|
||||
}
|
||||
|
@ -853,14 +866,14 @@ COMMANDS:
|
|||
clientGame.handleWin()
|
||||
case bgammon.CommandReset:
|
||||
if clientGame == nil {
|
||||
cmd.client.sendNotice("You are not currently in a match.")
|
||||
cmd.client.sendNotice(gotext.GetD(cmd.client.language, "You are not currently in a match."))
|
||||
continue
|
||||
} else if clientGame.Winner != 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
if clientGame.Turn != cmd.client.playerNumber {
|
||||
cmd.client.sendNotice("It is not your turn.")
|
||||
cmd.client.sendNotice(gotext.GetD(cmd.client.language, "It is not your turn."))
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -889,7 +902,7 @@ COMMANDS:
|
|||
}
|
||||
case bgammon.CommandOk, "k":
|
||||
if clientGame == nil {
|
||||
cmd.client.sendNotice("You are not currently in a match.")
|
||||
cmd.client.sendNotice(gotext.GetD(cmd.client.language, "You are not currently in a match."))
|
||||
continue
|
||||
} else if clientGame.Winner != 0 {
|
||||
continue
|
||||
|
@ -897,7 +910,7 @@ COMMANDS:
|
|||
|
||||
opponent := clientGame.opponent(cmd.client)
|
||||
if opponent == nil {
|
||||
cmd.client.sendNotice("You must wait until your opponent rejoins the match before continuing the game.")
|
||||
cmd.client.sendNotice(gotext.GetD(cmd.client.language, "You must wait until your opponent rejoins the match before continuing the game."))
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -905,7 +918,7 @@ COMMANDS:
|
|||
if clientGame.Turn != cmd.client.playerNumber {
|
||||
opponent := clientGame.opponent(cmd.client)
|
||||
if opponent == nil {
|
||||
cmd.client.sendNotice("You may not accept the double until your opponent rejoins the match.")
|
||||
cmd.client.sendNotice(gotext.GetD(cmd.client.language, "You may not accept the double until your opponent rejoins the match."))
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -914,24 +927,24 @@ COMMANDS:
|
|||
clientGame.DoublePlayer = cmd.client.playerNumber
|
||||
clientGame.NextPartialTurn(opponent.playerNumber)
|
||||
|
||||
cmd.client.sendNotice("Accepted double.")
|
||||
opponent.sendNotice(fmt.Sprintf("%s accepted double.", cmd.client.name))
|
||||
cmd.client.sendNotice(gotext.GetD(cmd.client.language, "Accepted double."))
|
||||
opponent.sendNotice(fmt.Sprintf(gotext.GetD(opponent.language, "%s accepted double."), cmd.client.name))
|
||||
|
||||
clientGame.replay = append(clientGame.replay, []byte(fmt.Sprintf("%d d %d 1", clientGame.Turn, clientGame.DoubleValue)))
|
||||
clientGame.eachClient(func(client *serverClient) {
|
||||
clientGame.sendBoard(client, false)
|
||||
})
|
||||
} else {
|
||||
cmd.client.sendNotice("Waiting for response from opponent.")
|
||||
cmd.client.sendNotice(gotext.GetD(cmd.client.language, "Waiting for response from opponent."))
|
||||
}
|
||||
continue
|
||||
} else if clientGame.Turn != cmd.client.playerNumber {
|
||||
cmd.client.sendNotice("It is not your turn.")
|
||||
cmd.client.sendNotice(gotext.GetD(cmd.client.language, "It is not your turn."))
|
||||
continue
|
||||
}
|
||||
|
||||
if clientGame.Roll1 == 0 || clientGame.Roll2 == 0 {
|
||||
cmd.client.sendNotice("You must roll first.")
|
||||
cmd.client.sendNotice(gotext.GetD(cmd.client.language, "You must roll first."))
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -940,7 +953,7 @@ COMMANDS:
|
|||
available := bgammon.FlipMoves(legalMoves, cmd.client.playerNumber, clientGame.Variant)
|
||||
bgammon.SortMoves(available)
|
||||
cmd.client.sendEvent(&bgammon.EventFailedOk{
|
||||
Reason: fmt.Sprintf("The following legal moves are available: %s", bgammon.FormatMoves(available)),
|
||||
Reason: fmt.Sprintf(gotext.GetD(cmd.client.language, "The following legal moves are available: %s"), bgammon.FormatMoves(available)),
|
||||
})
|
||||
continue
|
||||
}
|
||||
|
@ -952,7 +965,7 @@ COMMANDS:
|
|||
}
|
||||
if doubles < 1 || doubles > 6 {
|
||||
cmd.client.sendEvent(&bgammon.EventFailedOk{
|
||||
Reason: "Choose which doubles you want for your acey-deucey.",
|
||||
Reason: gotext.GetD(cmd.client.language, "Choose which doubles you want for your acey-deucey."),
|
||||
})
|
||||
continue
|
||||
}
|
||||
|
@ -977,8 +990,8 @@ COMMANDS:
|
|||
clientGame.nextTurn(true)
|
||||
clientGame.Roll1, clientGame.Roll2 = 0, 0
|
||||
if !clientGame.roll(cmd.client.playerNumber) {
|
||||
cmd.client.Terminate("Server error")
|
||||
opponent.Terminate("Server error")
|
||||
cmd.client.Terminate(gotext.GetD(cmd.client.language, "Server error"))
|
||||
opponent.Terminate(gotext.GetD(opponent.language, "Server error"))
|
||||
continue
|
||||
}
|
||||
clientGame.Reroll = false
|
||||
|
@ -998,16 +1011,16 @@ COMMANDS:
|
|||
}
|
||||
case bgammon.CommandRematch, "rm":
|
||||
if clientGame == nil {
|
||||
cmd.client.sendNotice("You are not currently in a match.")
|
||||
cmd.client.sendNotice(gotext.GetD(cmd.client.language, "You are not currently in a match."))
|
||||
continue
|
||||
} else if clientGame.Winner == 0 {
|
||||
cmd.client.sendNotice("The match you are in is still in progress.")
|
||||
cmd.client.sendNotice(gotext.GetD(cmd.client.language, "The match you are in is still in progress."))
|
||||
continue
|
||||
} else if clientGame.rematch == cmd.client.playerNumber {
|
||||
cmd.client.sendNotice("You have already requested a rematch.")
|
||||
cmd.client.sendNotice(gotext.GetD(cmd.client.language, "You have already requested a rematch."))
|
||||
continue
|
||||
} else if clientGame.client1 == nil || clientGame.client2 == nil {
|
||||
cmd.client.sendNotice("Your opponent left the match.")
|
||||
cmd.client.sendNotice(gotext.GetD(cmd.client.language, "Your opponent left the match."))
|
||||
continue
|
||||
} else if clientGame.rematch != 0 && clientGame.rematch != cmd.client.playerNumber {
|
||||
s.gamesLock.Lock()
|
||||
|
@ -1072,20 +1085,20 @@ COMMANDS:
|
|||
} else {
|
||||
clientGame.rematch = cmd.client.playerNumber
|
||||
|
||||
clientGame.opponent(cmd.client).sendNotice("Your opponent would like to play again. Type /rematch to accept.")
|
||||
cmd.client.sendNotice("Rematch offer sent.")
|
||||
clientGame.opponent(cmd.client).sendNotice(fmt.Sprintf(gotext.GetD(clientGame.opponent(cmd.client).language, "Your opponent would like to play again. Type %s to accept."), "/rematch"))
|
||||
cmd.client.sendNotice(gotext.GetD(cmd.client.language, "Rematch offer sent."))
|
||||
continue
|
||||
}
|
||||
case bgammon.CommandBoard, "b":
|
||||
if clientGame == nil {
|
||||
cmd.client.sendNotice("You are not currently in a match.")
|
||||
cmd.client.sendNotice(gotext.GetD(cmd.client.language, "You are not currently in a match."))
|
||||
continue
|
||||
}
|
||||
|
||||
clientGame.sendBoard(cmd.client, false)
|
||||
case bgammon.CommandPassword:
|
||||
if cmd.client.account == nil {
|
||||
cmd.client.sendNotice("Failed to change password: you are logged in as a guest.")
|
||||
cmd.client.sendNotice(gotext.GetD(cmd.client.language, "Failed to change password: you are logged in as a guest."))
|
||||
continue
|
||||
} else if len(params) < 2 {
|
||||
cmd.client.sendNotice("Please specify your old and new passwords as follows: password <old> <new>")
|
||||
|
@ -1094,16 +1107,16 @@ COMMANDS:
|
|||
|
||||
a, err := loginAccount(s.passwordSalt, cmd.client.name, params[0])
|
||||
if err != nil || a == nil || a.id == 0 {
|
||||
cmd.client.sendNotice("Failed to change password: incorrect existing password.")
|
||||
cmd.client.sendNotice(gotext.GetD(cmd.client.language, "Failed to change password: incorrect existing password."))
|
||||
continue
|
||||
}
|
||||
|
||||
err = setAccountPassword(s.passwordSalt, a.id, string(bytes.Join(params[1:], []byte("_"))))
|
||||
if err != nil {
|
||||
cmd.client.sendNotice("Failed to change password.")
|
||||
cmd.client.sendNotice(gotext.GetD(cmd.client.language, "Failed to change password."))
|
||||
continue
|
||||
}
|
||||
cmd.client.sendNotice("Password changed successfully.")
|
||||
cmd.client.sendNotice(gotext.GetD(cmd.client.language, "Password changed successfully."))
|
||||
case bgammon.CommandSet:
|
||||
if len(params) < 2 {
|
||||
cmd.client.sendNotice("Please specify the setting name and value as follows: set <name> <value>")
|
||||
|
@ -1154,17 +1167,17 @@ COMMANDS:
|
|||
} else {
|
||||
id, err = strconv.Atoi(string(params[0]))
|
||||
if err != nil || id < 0 {
|
||||
cmd.client.sendNotice("Invalid replay ID provided.")
|
||||
cmd.client.sendNotice(gotext.GetD(cmd.client.language, "Invalid replay ID provided."))
|
||||
continue
|
||||
}
|
||||
replay, err = replayByID(id)
|
||||
if err != nil {
|
||||
cmd.client.sendNotice("Invalid replay ID provided.")
|
||||
cmd.client.sendNotice(gotext.GetD(cmd.client.language, "Invalid replay ID provided."))
|
||||
continue
|
||||
}
|
||||
}
|
||||
if len(replay) == 0 {
|
||||
cmd.client.sendNotice("No replay was recorded for that game.")
|
||||
cmd.client.sendNotice(gotext.GetD(cmd.client.language, "No replay was recorded for that game."))
|
||||
continue
|
||||
}
|
||||
cmd.client.sendEvent(&bgammon.EventReplay{
|
||||
|
@ -1188,7 +1201,7 @@ COMMANDS:
|
|||
|
||||
matches, err := matchHistory(string(params[0]))
|
||||
if err != nil {
|
||||
cmd.client.sendNotice("Invalid replay ID provided.")
|
||||
cmd.client.sendNotice(gotext.GetD(cmd.client.language, "Invalid replay ID provided."))
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -1229,12 +1242,12 @@ COMMANDS:
|
|||
// Do nothing.
|
||||
case "endgame":
|
||||
if !allowDebugCommands {
|
||||
cmd.client.sendNotice("You are not allowed to use that command.")
|
||||
cmd.client.sendNotice(gotext.GetD(cmd.client.language, "You are not allowed to use that command."))
|
||||
continue
|
||||
}
|
||||
|
||||
if clientGame == nil {
|
||||
cmd.client.sendNotice("You are not currently in a match.")
|
||||
cmd.client.sendNotice(gotext.GetD(cmd.client.language, "You are not currently in a match."))
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -1254,7 +1267,7 @@ COMMANDS:
|
|||
})
|
||||
default:
|
||||
log.Printf("Received unknown command from client %s: %s", cmd.client.label(), cmd.command)
|
||||
cmd.client.sendNotice(fmt.Sprintf("Unknown command: %s", cmd.command))
|
||||
cmd.client.sendNotice(fmt.Sprintf(gotext.GetD(cmd.client.language, "Unknown command: %s"), cmd.command))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue