Compare commits
1537 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
19233e02d8 | ||
|
|
063bad8a18 | ||
|
|
557dec4612 | ||
|
|
97b764367a | ||
|
|
bf20ca1a6f | ||
|
|
999709dd7a | ||
|
|
393fb487e0 | ||
|
|
2703593fcd | ||
|
|
7bb8e01b54 | ||
|
|
1d65646de3 | ||
|
|
8e7b1e9b06 | ||
|
|
6418c18739 | ||
|
|
833e0908a4 | ||
|
|
124d4468c4 | ||
|
|
46ba8af111 | ||
|
|
033dd8088e | ||
|
|
656fbf78fa | ||
|
|
a6993fa15f | ||
|
|
0f31ddd868 | ||
|
|
61e40b800e | ||
|
|
a8945997f7 | ||
|
|
aa160e397a | ||
|
|
c07cfbcf40 | ||
|
|
a7b2b39fd2 | ||
|
|
4dbb8de2e9 | ||
|
|
d161d06602 | ||
|
|
715762e80c | ||
|
|
97342e2c60 | ||
|
|
d709e81adf | ||
|
|
f2da1279a7 | ||
|
|
928b149d66 | ||
|
|
9d9f839a75 | ||
|
|
981e1d0d57 | ||
|
|
a89a745d8c | ||
|
|
c9e97c91bf | ||
|
|
71834aaf7e | ||
|
|
22e29b7564 | ||
|
|
578213ee50 | ||
|
|
c0fe7338ef | ||
|
|
57b2425569 | ||
|
|
b79cb08aca | ||
|
|
ed7cd0d962 | ||
|
|
7a04463517 | ||
|
|
34099258a7 | ||
|
|
19e4c292c7 | ||
|
|
2cbc354cb3 | ||
|
|
47de734e17 | ||
|
|
ae558370d5 | ||
|
|
4c966b46c4 | ||
|
|
dab7c252b4 | ||
|
|
420d0d6d9e | ||
|
|
2ba880d869 | ||
|
|
f62cd62952 | ||
|
|
820ae5bbfa | ||
|
|
5a04b66a1c | ||
|
|
1b54ab5f43 | ||
|
|
c090807cb3 | ||
|
|
9574295f8d | ||
|
|
bc417b6301 | ||
|
|
a4efd1bac1 | ||
|
|
36d0eed502 | ||
|
|
2aa7947dad | ||
|
|
6d46b9de85 | ||
|
|
de33ba1221 | ||
|
|
3468f8f220 | ||
|
|
381a932b06 | ||
|
|
186eba9d55 | ||
|
|
bf5eafc0e0 | ||
|
|
f3ce3249cc | ||
|
|
92417342bf | ||
|
|
d190c2edf8 | ||
|
|
e0b255a859 | ||
|
|
d38bb332d6 | ||
|
|
aa4656da0a | ||
|
|
bb32b5b124 | ||
|
|
ef03eb4581 | ||
|
|
72ccca583b | ||
|
|
3dda192a6f | ||
|
|
171aab883a | ||
|
|
0316e06823 | ||
|
|
e3d7370ff6 | ||
|
|
b1c72db334 | ||
|
|
1b0b77978c | ||
|
|
d2d31d94ab | ||
|
|
3c8f9a8eb6 | ||
|
|
519c8a7a68 | ||
|
|
852eb088fa | ||
|
|
57d2ab0f69 | ||
|
|
fdbeb25af2 | ||
|
|
7b18ddbbdd | ||
|
|
05c5c5dcaa | ||
|
|
7270808f80 | ||
|
|
31e41bab0f | ||
|
|
ee9b19b98c | ||
|
|
658fd9e2b8 | ||
|
|
c72819f253 | ||
|
|
32d66d96fd | ||
|
|
1b125ca222 | ||
|
|
1e7fac37b8 | ||
|
|
2341d2d144 | ||
|
|
66f985f758 | ||
|
|
95c4c4ee2e | ||
|
|
7df724a8d6 | ||
|
|
01fc89f874 | ||
|
|
7d5161a44d | ||
|
|
2a43279167 | ||
|
|
469e52f984 | ||
|
|
76e18cac7b | ||
|
|
9dec8fa266 | ||
|
|
b1b22e06d8 | ||
|
|
630064912a | ||
|
|
1f1aa56d1b | ||
|
|
fa8e1a93d7 | ||
|
|
47ffc52955 | ||
|
|
cb5c5e91f7 | ||
|
|
a2997b3be5 | ||
|
|
4caadbf837 | ||
|
|
0020a4af8c | ||
|
|
4f9b7ed56d | ||
|
|
53c573d7e0 | ||
|
|
ff3c6468cf | ||
|
|
9b653d37e6 | ||
|
|
6450c857ce | ||
|
|
410d918a75 | ||
|
|
1639ee330f | ||
|
|
a386b1e29f | ||
|
|
715e88a41e | ||
|
|
77ff241698 | ||
|
|
37ef7dd434 | ||
|
|
631944f2be | ||
|
|
fac56917a9 | ||
|
|
1a61c7fd1c | ||
|
|
a3622b43f0 | ||
|
|
0abecb446e | ||
|
|
5647721a41 | ||
|
|
a54b6a4175 | ||
|
|
b26297c864 | ||
|
|
bb820093ff | ||
|
|
f50c7f6e86 | ||
|
|
beda327165 | ||
|
|
d9eb329bea | ||
|
|
c28bf27f8f | ||
|
|
c18a8cc3ce | ||
|
|
485280243a | ||
|
|
fefc3e6eae | ||
|
|
89f9b84819 | ||
|
|
3c4824e59e | ||
|
|
ea603fd617 | ||
|
|
37bb6f8a70 | ||
|
|
8dbefbe3d9 | ||
|
|
8a79ce2b64 | ||
|
|
892d81907e | ||
|
|
50a4a9d9c2 | ||
|
|
55c40cf077 | ||
|
|
511a69454d | ||
|
|
e69ec1d786 | ||
|
|
f619449137 | ||
|
|
6547a4a9db | ||
|
|
fc830c47d9 | ||
|
|
5b0bda5291 | ||
|
|
da5b8f040b | ||
|
|
65bc278a06 | ||
|
|
a882a010d3 | ||
|
|
ce5c64f789 | ||
|
|
7c95366d59 | ||
|
|
bc55208047 | ||
|
|
d9212ee249 | ||
|
|
917c084ba1 | ||
|
|
6dc3be91f6 | ||
|
|
3a82f1cda8 | ||
|
|
aa337c2e63 | ||
|
|
5f00cf6a14 | ||
|
|
5b70a69ca1 | ||
|
|
7175dd3c78 | ||
|
|
e1022d475e | ||
|
|
df883aeea7 | ||
|
|
ac736dc6bd | ||
|
|
b966557d03 | ||
|
|
b8309ca89d | ||
|
|
4fcae1b8f0 | ||
|
|
db3a30b61d | ||
|
|
0e97028a25 | ||
|
|
20cd54b84f | ||
|
|
ed7e2d7625 | ||
|
|
ed981184d3 | ||
|
|
aa7ee2a381 | ||
|
|
c72761d627 | ||
|
|
a2a8da873e | ||
|
|
385d571c3a | ||
|
|
0e01178669 | ||
|
|
dfc6f986bc | ||
|
|
e892469ff9 | ||
|
|
4422dbc527 | ||
|
|
850cceecaa | ||
|
|
5e9710d2f3 | ||
|
|
2ae819376f | ||
|
|
33dc62db36 | ||
|
|
a1d97a1ab6 | ||
|
|
fa633cf184 | ||
|
|
3afcbdf2eb | ||
|
|
dff655484e | ||
|
|
49b6a6a928 | ||
|
|
8bf48093b7 | ||
|
|
a22e318c22 | ||
|
|
1e0ca0db80 | ||
|
|
0b2fdf49c3 | ||
|
|
ee8e3b9a5f | ||
|
|
fd4ab739bf | ||
|
|
b0e2c5672c | ||
|
|
64901ca8b0 | ||
|
|
5bdd93cbef | ||
|
|
766bcfd30b | ||
|
|
698aec8556 | ||
|
|
df9139cec8 | ||
|
|
ed57b527a3 | ||
|
|
b3689ca93d | ||
|
|
cf5f30cebb | ||
|
|
a33320065c | ||
|
|
0e391bc071 | ||
|
|
b856dfb5ff | ||
|
|
f38206184c | ||
|
|
d10124fdb2 | ||
|
|
1b545ea1b7 | ||
|
|
2d6bcc09b9 | ||
|
|
35f35d0a97 | ||
|
|
20dd3f6683 | ||
|
|
532dba9873 | ||
|
|
3de1b738a3 | ||
|
|
b7472d7ab3 | ||
|
|
8a6f0b4e92 | ||
|
|
776a05e959 | ||
|
|
abeabab66b | ||
|
|
295f7f9222 | ||
|
|
29a466dfb2 | ||
|
|
2c8af266b7 | ||
|
|
41ee2e48d4 | ||
|
|
11f7b4960d | ||
|
|
a10b2fefa7 | ||
|
|
c26c3086af | ||
|
|
2835465e0d | ||
|
|
d1111725ef | ||
|
|
d310ce93f6 | ||
|
|
5b7812c469 | ||
|
|
623baec632 | ||
|
|
468e65e8da | ||
|
|
f9d33219f5 | ||
|
|
1b51313cf0 | ||
|
|
7339e3c634 | ||
|
|
e6378568b1 | ||
|
|
260e623dfc | ||
|
|
c9742c54ee | ||
|
|
437eeac1dd | ||
|
|
f026927a10 | ||
|
|
87c3448dce | ||
|
|
738015e1d3 | ||
|
|
67cff6a431 | ||
|
|
4a0788729a | ||
|
|
324ec44b1f | ||
|
|
52a24f3376 | ||
|
|
4e8da1047f | ||
|
|
b9bd656130 | ||
|
|
62b8959806 | ||
|
|
f3a764e2dc | ||
|
|
97f8e3b96d | ||
|
|
8b236925c2 | ||
|
|
088208a3bb | ||
|
|
2084223308 | ||
|
|
e4ba7fd004 | ||
|
|
c94e97dbe6 | ||
|
|
8142cac415 | ||
|
|
13e580caaa | ||
|
|
1c058d5546 | ||
|
|
b41130b6fa | ||
|
|
8328ac6b63 | ||
|
|
60785c9909 | ||
|
|
1674ae161f | ||
|
|
9d4a2c9f15 | ||
|
|
8967922db6 | ||
|
|
ceb3c93df0 | ||
|
|
3703b2396a | ||
|
|
ccc02de315 | ||
|
|
05b5341a1d | ||
|
|
b68d8bd4d5 | ||
|
|
17340f056d | ||
|
|
806780b5b3 | ||
|
|
b66bfa0209 | ||
|
|
f42dd2dd95 | ||
|
|
b4317cf3c4 | ||
|
|
6172c12227 | ||
|
|
4e832972fa | ||
|
|
30f32e1da0 | ||
|
|
0f2aedb150 | ||
|
|
6560eb19ac | ||
|
|
69cbb39221 | ||
|
|
fb4367080d | ||
|
|
e6f7db6cca | ||
|
|
e2200be3ff | ||
|
|
8345076c28 | ||
|
|
46a76843a9 | ||
|
|
e5730c206e | ||
|
|
f17e2948a3 | ||
|
|
56157dd32c | ||
|
|
9b08cdebe6 | ||
|
|
a80d65ccd2 | ||
|
|
fdcb4faef9 | ||
|
|
75ae03be9f | ||
|
|
c1f9d0aa20 | ||
|
|
5da2f68a0c | ||
|
|
00809c8484 | ||
|
|
87aef36237 | ||
|
|
25cfbf30a2 | ||
|
|
6824df5a1c | ||
|
|
52fbce102f | ||
|
|
f14c0ba5d2 | ||
|
|
d9aedbdf55 | ||
|
|
e26266f1d7 | ||
|
|
123f4d2e1c | ||
|
|
bd96bfa29e | ||
|
|
90e1115798 | ||
|
|
8d496bfbda | ||
|
|
e59cbc9360 | ||
|
|
f621b938bd | ||
|
|
1c667bc066 | ||
|
|
7f085b6b80 | ||
|
|
34126d990a | ||
|
|
650bb1136f | ||
|
|
0a610a79bb | ||
|
|
cc77fff573 | ||
|
|
cbd054f050 | ||
|
|
feeef9c449 | ||
|
|
56f400a4ef | ||
|
|
524a0cfa0f | ||
|
|
1730d81990 | ||
|
|
8bf726f9a3 | ||
|
|
7cab2e6eb1 | ||
|
|
d60c56a767 | ||
|
|
746ad76a5b | ||
|
|
22c20dd8b3 | ||
|
|
69e4c823c4 | ||
|
|
ecf37639a5 | ||
|
|
e9d1565115 | ||
|
|
167e5dd28c | ||
|
|
b0fb5d0469 | ||
|
|
cee1ff220b | ||
|
|
4c9b3abae0 | ||
|
|
6acc529698 | ||
|
|
e622273a73 | ||
|
|
bd36f98954 | ||
|
|
1ed7fa71b9 | ||
|
|
94a056c18a | ||
|
|
892b6408d3 | ||
|
|
dd90f57f70 | ||
|
|
5586a4aa4f | ||
|
|
f81facf4cd | ||
|
|
edceb1cf1e | ||
|
|
dd6fdde8ce | ||
|
|
21ae017443 | ||
|
|
2e50f58a09 | ||
|
|
3d2cfa9380 | ||
|
|
104ab707a6 | ||
|
|
ab269ac8a6 | ||
|
|
08eeeb2a40 | ||
|
|
c0858e20f0 | ||
|
|
50c42e705d | ||
|
|
1782094f92 | ||
|
|
f435b444d7 | ||
|
|
54bf168f80 | ||
|
|
7e4a4c2bd4 | ||
|
|
deb90ba749 | ||
|
|
1ce0f639ce | ||
|
|
bf1b96fbb5 | ||
|
|
19881f2d09 | ||
|
|
0a48a58317 | ||
|
|
afd9c276f3 | ||
|
|
6dfb61ada9 | ||
|
|
48aae65afd | ||
|
|
f063cd199c | ||
|
|
87e8b9a261 | ||
|
|
804ee3251d | ||
|
|
497efd6e2d | ||
|
|
59bbfcd710 | ||
|
|
7d6a040cec | ||
|
|
ade21206c6 | ||
|
|
eaffa63ae8 | ||
|
|
5354e1bca0 | ||
|
|
158b7a840a | ||
|
|
9f8e2460ac | ||
|
|
48ddddb680 | ||
|
|
0df389240e | ||
|
|
650db03198 | ||
|
|
1d0ed79b13 | ||
|
|
ce8dabf112 | ||
|
|
9d9c5634e2 | ||
|
|
dcb0396a73 | ||
|
|
2612647e74 | ||
|
|
e1f086fb85 | ||
|
|
248405d984 | ||
|
|
02002e6c16 | ||
|
|
b9f6cceda1 | ||
|
|
c734417b1c | ||
|
|
739a328674 | ||
|
|
cf8b5f9c23 | ||
|
|
608d7d4168 | ||
|
|
dceed4be1e | ||
|
|
4f9d047196 | ||
|
|
9ac20a99b6 | ||
|
|
60725fca2a | ||
|
|
88b855d949 | ||
|
|
98c187869b | ||
|
|
0a53f88af7 | ||
|
|
4b471ad95d | ||
|
|
ed7ec40d34 | ||
|
|
59a8d692b1 | ||
|
|
d326a8c4cf | ||
|
|
2b5f0e099f | ||
|
|
5c0ea843a0 | ||
|
|
83568e3c23 | ||
|
|
42d59026fd | ||
|
|
f5fef79619 | ||
|
|
4cf882ecd2 | ||
|
|
cf11a71f03 | ||
|
|
2ca9f004bd | ||
|
|
07935149a7 | ||
|
|
f99ece7531 | ||
|
|
dd142fceaa | ||
|
|
eb3e1e376e | ||
|
|
b6a3b6f0be | ||
|
|
f962718717 | ||
|
|
caff1b207a | ||
|
|
09a48aa1ed | ||
|
|
a7bbfc3d59 | ||
|
|
a387920c1f | ||
|
|
8ed0cf8889 | ||
|
|
462f60a5da | ||
|
|
2b8ce93ab1 | ||
|
|
f8084e8baf | ||
|
|
e3661d11b5 | ||
|
|
798004b2a3 | ||
|
|
d7a1eededb | ||
|
|
857923f268 | ||
|
|
0f4cae323e | ||
|
|
9ec87776f0 | ||
|
|
e21aac1c08 | ||
|
|
d123fc93d5 | ||
|
|
5768776e56 | ||
|
|
a9e07f103a | ||
|
|
b336e42f21 | ||
|
|
ef1125b75d | ||
|
|
30eab6db4b | ||
|
|
e884b20e32 | ||
|
|
7e58fd3f4b | ||
|
|
68c8cfe620 | ||
|
|
b25a10f2fe | ||
|
|
c0f02217c1 | ||
|
|
0036ff96c7 | ||
|
|
2c33c24d42 | ||
|
|
98fcc02e38 | ||
|
|
50c6c07140 | ||
|
|
0e86975563 | ||
|
|
9dfa884349 | ||
|
|
28de534bd4 | ||
|
|
574b9f49a1 | ||
|
|
728656d23b | ||
|
|
3b02cd1241 | ||
|
|
408bd4df5b | ||
|
|
d16e2b3e25 | ||
|
|
dd9e934f2d | ||
|
|
c814fac8ba | ||
|
|
d3fde0949a | ||
|
|
bc6320d11d | ||
|
|
1feed48e0f | ||
|
|
dd48b8354c | ||
|
|
adaf454d36 | ||
|
|
17ac92f5a1 | ||
|
|
54dba4b18a | ||
|
|
420f0a2e2c | ||
|
|
11d38f9483 | ||
|
|
f64d18de82 | ||
|
|
eaaad55a10 | ||
|
|
65af33758b | ||
|
|
6f4366dffc | ||
|
|
d5735710cd | ||
|
|
bd6c3380ba | ||
|
|
eb7cee0292 | ||
|
|
b29eee3a1a | ||
|
|
58033e959f | ||
|
|
b1347f48cb | ||
|
|
1520798201 | ||
|
|
b8662c3afd | ||
|
|
5dde9f9f9f | ||
|
|
3466a7f0fb | ||
|
|
89849854bb | ||
|
|
8348e26ac4 | ||
|
|
9512b7b0e0 | ||
|
|
c1f32bc792 | ||
|
|
dc4f33b1f5 | ||
|
|
6fd2d3a039 | ||
|
|
865cc45c59 | ||
|
|
03eca57bb5 | ||
|
|
5a9b2a0fa8 | ||
|
|
d1d63de3bf | ||
|
|
cc2fbb53d8 | ||
|
|
fde2821109 | ||
|
|
e4e1b93a9a | ||
|
|
b48aeea1d8 | ||
|
|
88b1b3601e | ||
|
|
2b54cd128f | ||
|
|
1fc341b77b | ||
|
|
2aa0ccbd58 | ||
|
|
6471ccda73 | ||
|
|
822ae4c6ef | ||
|
|
7dcd683997 | ||
|
|
d17992a6f1 | ||
|
|
af72af6ec4 | ||
|
|
f6a43e8a21 | ||
|
|
4245b7e1d1 | ||
|
|
7a4586b1ef | ||
|
|
f611eccec9 | ||
|
|
eb71e599a2 | ||
|
|
f385a7f546 | ||
|
|
8c5f31d7a8 | ||
|
|
efab82709f | ||
|
|
baf4914f9b | ||
|
|
9080c8870a | ||
|
|
b6915f5073 | ||
|
|
a232698664 | ||
|
|
58c36d9180 | ||
|
|
61f065747e | ||
|
|
bcd385210a | ||
|
|
259814ab90 | ||
|
|
5ad2b64fc4 | ||
|
|
f4c9972fdf | ||
|
|
f25fbb2d4e | ||
|
|
3a10713337 | ||
|
|
d9d025fa95 | ||
|
|
f8363ff994 | ||
|
|
745ebaced4 | ||
|
|
dc2e1d8ea4 | ||
|
|
1191168a19 | ||
|
|
4421b9f613 | ||
|
|
8fabdd7137 | ||
|
|
91e5b48fe5 | ||
|
|
4dc6dcbee7 | ||
|
|
8c5b63a49a | ||
|
|
ca4a593d69 | ||
|
|
200cbaec68 | ||
|
|
39cf03a4ab | ||
|
|
c8f859d7e4 | ||
|
|
b7f2ed2e50 | ||
|
|
2ba0f54cb4 | ||
|
|
0e425f0355 | ||
|
|
14807a52ed | ||
|
|
ed99982d86 | ||
|
|
d85c048d8b | ||
|
|
0c979e7ff1 | ||
|
|
f1b0f96c07 | ||
|
|
0ac249ad30 | ||
|
|
b1af9103bf | ||
|
|
cd303b5658 | ||
|
|
3bd4a88221 | ||
|
|
1dfa4cda64 | ||
|
|
d0aec519d1 | ||
|
|
edae9c0a5e | ||
|
|
2ee93f2408 | ||
|
|
300d307b87 | ||
|
|
187742a6ca | ||
|
|
fe0fe15890 | ||
|
|
ee2a87988b | ||
|
|
7c30d076fb | ||
|
|
5ab3f9847a | ||
|
|
57b7ac838c | ||
|
|
513ec5597d | ||
|
|
3ec6de9b1e | ||
|
|
b749304e82 | ||
|
|
9b17d14437 | ||
|
|
8428678712 | ||
|
|
2b816c3370 | ||
|
|
e229ab8f98 | ||
|
|
17689cab25 | ||
|
|
6fc48de7ae | ||
|
|
20cb57a7f8 | ||
|
|
9d7bad07d1 | ||
|
|
4eeeffa4d6 | ||
|
|
5df375128c | ||
|
|
4c59b75e17 | ||
|
|
5e113715c8 | ||
|
|
82daf12862 | ||
|
|
8860026ff1 | ||
|
|
17d71f499b | ||
|
|
013b666a75 | ||
|
|
522f7bb036 | ||
|
|
a6a3b44f94 | ||
|
|
31c17a7766 | ||
|
|
28135b26ad | ||
|
|
c808db5db5 | ||
|
|
6b64677a12 | ||
|
|
f4fded038b | ||
|
|
42c88a9ffe | ||
|
|
80fc8fa0c6 | ||
|
|
2af5bff831 | ||
|
|
e97c46a09f | ||
|
|
bd792c72b8 | ||
|
|
23c232d0d3 | ||
|
|
74ead0b4e6 | ||
|
|
7d3e299877 | ||
|
|
bf5cbc9d5d | ||
|
|
4bfc5266b6 | ||
|
|
780a2150fb | ||
|
|
702d216a06 | ||
|
|
099f76a1ce | ||
|
|
627ee5c80b | ||
|
|
e065a15028 | ||
|
|
502943250a | ||
|
|
21e54e98fc | ||
|
|
3010cffe03 | ||
|
|
94ca75092b | ||
|
|
4305144472 | ||
|
|
0d258ccf3e | ||
|
|
380a005143 | ||
|
|
120d83901a | ||
|
|
0da23102a7 | ||
|
|
78bfb4eb2d | ||
|
|
2d68b7e2af | ||
|
|
f04b58b091 | ||
|
|
e038ca4ad4 | ||
|
|
551afa682a | ||
|
|
2149ee404b | ||
|
|
b49d7dbec3 | ||
|
|
dfb54e70f7 | ||
|
|
0dc7af2515 | ||
|
|
808e3ebf1b | ||
|
|
78221562cf | ||
|
|
3992d23f46 | ||
|
|
04c33850c0 | ||
|
|
8ee4ed3e93 | ||
|
|
74a8ba6d1b | ||
|
|
ff78509bc0 | ||
|
|
b2ea831498 | ||
|
|
144d30df98 | ||
|
|
6c62608929 | ||
|
|
bce5d809df | ||
|
|
9510ea96bc | ||
|
|
ae342334e8 | ||
|
|
61e69019b1 | ||
|
|
c883fb185e | ||
|
|
ba33d77e1e | ||
|
|
d3823bd9ca | ||
|
|
bf485f132c | ||
|
|
e8d0c38d59 | ||
|
|
30314bc979 | ||
|
|
e7e59cf739 | ||
|
|
f07499aa6c | ||
|
|
4566a4fa4b | ||
|
|
1886d56013 | ||
|
|
1b259919f7 | ||
|
|
66a40023e6 | ||
|
|
1da1ddf48a | ||
|
|
ddc051eebc | ||
|
|
3b9eba9a48 | ||
|
|
153493bd40 | ||
|
|
0c4104de41 | ||
|
|
6c78877c6a | ||
|
|
dddf7d3953 | ||
|
|
e11c24cc34 | ||
|
|
f14a49e072 | ||
|
|
849a75709c | ||
|
|
237a4c8d61 | ||
|
|
95a4c869ff | ||
|
|
c1137f6a72 | ||
|
|
687437dcb4 | ||
|
|
30a9d6c6eb | ||
|
|
f064cda204 | ||
|
|
d4a7447ae9 | ||
|
|
fef69f6edb | ||
|
|
e5cd774cc8 | ||
|
|
c87b55d74b | ||
|
|
103b70d5e8 | ||
|
|
af7afadf29 | ||
|
|
7c43add304 | ||
|
|
e65861c49f | ||
|
|
21cbfd6d82 | ||
|
|
b189bd633c | ||
|
|
0108996dd4 | ||
|
|
3aa1c3543e | ||
|
|
119b26b3d9 | ||
|
|
d80567c7b7 | ||
|
|
ae5a2e5732 | ||
|
|
5b2813d875 | ||
|
|
1d0a1f17b4 | ||
|
|
9fddde1ec3 | ||
|
|
17bd48f9fd | ||
|
|
e0f5d67ee6 | ||
|
|
169078a545 | ||
|
|
9ca619c75c | ||
|
|
c869bfbec2 | ||
|
|
e43b18b34a | ||
|
|
72ad6c5893 | ||
|
|
8be09db21c | ||
|
|
35b6f72d30 | ||
|
|
35d3fb5e81 | ||
|
|
05dd4e3ab7 | ||
|
|
a3665587e4 | ||
|
|
c3da735fe3 | ||
|
|
eebc7bcdce | ||
|
|
4512648ae7 | ||
|
|
d80d7adce5 | ||
|
|
94ea5b5751 | ||
|
|
5ecdfd81bd | ||
|
|
1344325fcc | ||
|
|
938d586ebf | ||
|
|
daff3f15a1 | ||
|
|
55b80c9135 | ||
|
|
9317aea2e3 | ||
|
|
558e443427 | ||
|
|
acfcd08d38 | ||
|
|
b6d5cbd5e2 | ||
|
|
f91ae551a0 | ||
|
|
871d2c564a | ||
|
|
e6b1bbd127 | ||
|
|
f28a9e7454 | ||
|
|
786c5d941d | ||
|
|
829a26dce0 | ||
|
|
41fe5c1c2c | ||
|
|
40becaa198 | ||
|
|
416a1067da | ||
|
|
30e11d1b50 | ||
|
|
302420b724 | ||
|
|
35499f2177 | ||
|
|
cca8a27f9a | ||
|
|
dda545ad0d | ||
|
|
cf4b4370e0 | ||
|
|
273d32d658 | ||
|
|
51246def30 | ||
|
|
53a5f0693f | ||
|
|
66ca58f075 | ||
|
|
3d9e697c04 | ||
|
|
475be1e5ae | ||
|
|
e53a023276 | ||
|
|
56fbd7ad3f | ||
|
|
91e9ebaea0 | ||
|
|
6f26efa8a5 | ||
|
|
d4104881c0 | ||
|
|
08a6960c9d | ||
|
|
0d649cc9b5 | ||
|
|
ecc3aec6af | ||
|
|
1602e3ded8 | ||
|
|
6ee551123f | ||
|
|
2b601c6d52 | ||
|
|
2d3c42bcb5 | ||
|
|
40f6fe40cd | ||
|
|
445cee80f6 | ||
|
|
cb4235baf7 | ||
|
|
14fd275cd9 | ||
|
|
72edb784fd | ||
|
|
d64fe56c22 | ||
|
|
9fec847b36 | ||
|
|
3759505847 | ||
|
|
2bd18208d4 | ||
|
|
de8777777b | ||
|
|
f54d558db5 | ||
|
|
31ed67dbed | ||
|
|
c3feafc38c | ||
|
|
d5470cd69e | ||
|
|
58be1191c5 | ||
|
|
4c9ebf13bb | ||
|
|
9e64882298 | ||
|
|
4d4611fb04 | ||
|
|
c1c30dc936 | ||
|
|
c869a2a3d5 | ||
|
|
754f52febf | ||
|
|
3d19b8ba7f | ||
|
|
c7f6ab790b | ||
|
|
0721c28dfc | ||
|
|
9bd9ca7fd8 | ||
|
|
bc23153c40 | ||
|
|
25a9032e6d | ||
|
|
e00a2292ae | ||
|
|
2446ba6a23 | ||
|
|
bedc0fdbdc | ||
|
|
787041b6ec | ||
|
|
9dde6ce4a7 | ||
|
|
4bd9ecdec2 | ||
|
|
50036af6a1 | ||
|
|
810067c37a | ||
|
|
d8e361ccc2 | ||
|
|
9d44143c90 | ||
|
|
daccee5ba4 | ||
|
|
dfe2931ab2 | ||
|
|
03d584c12c | ||
|
|
d84266817f | ||
|
|
4f24b30ba8 | ||
|
|
c65ba4d019 | ||
|
|
0b6b730ae5 | ||
|
|
0e526cadfd | ||
|
|
3cfef77824 | ||
|
|
58729f6500 | ||
|
|
5d61834398 | ||
|
|
0f535a2aea | ||
|
|
e79d7b6729 | ||
|
|
bf34ec773a | ||
|
|
6679f1638b | ||
|
|
f8d4ee070c | ||
|
|
8c002f7092 | ||
|
|
8e0947b054 | ||
|
|
3853663616 | ||
|
|
0b3961adc4 | ||
|
|
9faaaf86e2 | ||
|
|
618fc63604 | ||
|
|
c9b6c86139 | ||
|
|
35a6ae35ee | ||
|
|
18d6797e56 | ||
|
|
de6aa4db37 | ||
|
|
4b5788d8a3 | ||
|
|
47d4112999 | ||
|
|
659e9dc135 | ||
|
|
cd687ee1e2 | ||
|
|
6118aba235 | ||
|
|
fd246374da | ||
|
|
fcca991555 | ||
|
|
dce5b214ba | ||
|
|
5f214e2cb1 | ||
|
|
265038b8cb | ||
|
|
34ab97fb30 | ||
|
|
0a4ad94306 | ||
|
|
6ca18ac8f4 | ||
|
|
d836d785b4 | ||
|
|
de62790ff4 | ||
|
|
9cf0b15ec3 | ||
|
|
7c23a004c0 | ||
|
|
bab980b508 | ||
|
|
87c715cb84 | ||
|
|
04a9ca69c9 | ||
|
|
489a1ed7bc | ||
|
|
22ce441bcc | ||
|
|
54e283ed06 | ||
|
|
3fbf00c41c | ||
|
|
af28ca49a5 | ||
|
|
c490034238 | ||
|
|
4ef8aa86dc | ||
|
|
45f3e27de2 | ||
|
|
5155c77997 | ||
|
|
c513cb0255 | ||
|
|
cbeac8fd2a | ||
|
|
0bab2987ed | ||
|
|
e4dd46c0f7 | ||
|
|
6852df7484 | ||
|
|
e9ed6f0228 | ||
|
|
667f81f99d | ||
|
|
da8eefca45 | ||
|
|
e05fa5fbcf | ||
|
|
d39d1d206c | ||
|
|
0e327d9373 | ||
|
|
a3e70e6bf1 | ||
|
|
42e908a36a | ||
|
|
170a30be23 | ||
|
|
7a2f4de850 | ||
|
|
f125c77a0d | ||
|
|
22efb95048 | ||
|
|
a3d1d25bd1 | ||
|
|
e402917a85 | ||
|
|
8a1461d4af | ||
|
|
cd05ef1935 | ||
|
|
e4abe4ead6 | ||
|
|
59ec90f4ba | ||
|
|
c58c35c9ed | ||
|
|
b142411fc5 | ||
|
|
0765eaf13c | ||
|
|
6f7280e8b5 | ||
|
|
1d22f2052e | ||
|
|
12a8e16d0a | ||
|
|
83309a3c83 | ||
|
|
642703bc6a | ||
|
|
da2ae614f3 | ||
|
|
e8b91b8dd9 | ||
|
|
a77015015e | ||
|
|
054cbdf1e8 | ||
|
|
1714e9d27e | ||
|
|
d77a9f7e43 | ||
|
|
2677c1c7bc | ||
|
|
5df6d959d8 | ||
|
|
853e7775f9 | ||
|
|
82ec411046 | ||
|
|
ca0581553c | ||
|
|
eaa8a32b00 | ||
|
|
97c2c06c9a | ||
|
|
4972439ad6 | ||
|
|
a6493487c4 | ||
|
|
e8bce4c167 | ||
|
|
01c8479ad8 | ||
|
|
c5f974a39d | ||
|
|
989f68174a | ||
|
|
9d3f3bf6d7 | ||
|
|
b59093dfbb | ||
|
|
c2f8b7d9e4 | ||
|
|
673026b2ba | ||
|
|
b6d7913727 | ||
|
|
1cc633b5ac | ||
|
|
0c56cbd224 | ||
|
|
02b7884357 | ||
|
|
d79476b0d2 | ||
|
|
505f9a0dd6 | ||
|
|
12764c1070 | ||
|
|
53b065dd38 | ||
|
|
9f69ebb15d | ||
|
|
c19a82f119 | ||
|
|
8916d8489d | ||
|
|
bb826fdf47 | ||
|
|
4fee81001b | ||
|
|
2af6165372 | ||
|
|
ee22dd9770 | ||
|
|
a51e37490b | ||
|
|
0fb9c56de9 | ||
|
|
2fe1c75c4e | ||
|
|
7b086e99d2 | ||
|
|
cc3c693dc8 | ||
|
|
acf3a58515 | ||
|
|
e0ea39d02c | ||
|
|
23a60155c0 | ||
|
|
f3d088fa4d | ||
|
|
1870c4979d | ||
|
|
b6f28d7266 | ||
|
|
a574dabfe9 | ||
|
|
3f6ea08963 | ||
|
|
c1bc68bc43 | ||
|
|
a1a5d735d4 | ||
|
|
52e1427b08 | ||
|
|
c6b40c145c | ||
|
|
64531f94f4 | ||
|
|
9ffd430ae3 | ||
|
|
f6838d7bb9 | ||
|
|
6f36ee8920 | ||
|
|
031d22d195 | ||
|
|
72b4d08d93 | ||
|
|
97350e8bde | ||
|
|
9326a2a75c | ||
|
|
230b53e990 | ||
|
|
90bf326cf1 | ||
|
|
3fb89c3947 | ||
|
|
4212d46663 | ||
|
|
1976d60e35 | ||
|
|
6722304746 | ||
|
|
7bd781f032 | ||
|
|
43a27e9eba | ||
|
|
db9fb4ad85 | ||
|
|
61b4fe2c4e | ||
|
|
5ebb0daa01 | ||
|
|
6b1da9b2fb | ||
|
|
2754c5b787 | ||
|
|
41531e52fb | ||
|
|
bc1e788bd9 | ||
|
|
1145fd63ba | ||
|
|
5bc2d37de3 | ||
|
|
7f034659e3 | ||
|
|
61d865d6c5 | ||
|
|
dd5e04ed9f | ||
|
|
ca7becb3d4 | ||
|
|
f2517b95bd | ||
|
|
d881f0e679 | ||
|
|
bda7e96e30 | ||
|
|
3ac2336e76 | ||
|
|
5b2f8552e8 | ||
|
|
0be7aa3422 | ||
|
|
0896004185 | ||
|
|
af29896e76 | ||
|
|
4e50670358 | ||
|
|
7b9bf73b1a | ||
|
|
bde44a8a6d | ||
|
|
e7971ae3f6 | ||
|
|
dd9b66b368 | ||
|
|
b95f655b66 | ||
|
|
2ff05589c5 | ||
|
|
6c95148a63 | ||
|
|
43da244384 | ||
|
|
6437df189b | ||
|
|
f7089c55a7 | ||
|
|
17343a432e | ||
|
|
42e9b73764 | ||
|
|
5341353003 | ||
|
|
9c9c19c9a6 | ||
|
|
2ef0c6fabe | ||
|
|
461312dc87 | ||
|
|
87983240aa | ||
|
|
78b36ce4d4 | ||
|
|
1cb7532d8b | ||
|
|
ea66010137 | ||
|
|
38bf34520a | ||
|
|
7a03d82fcd | ||
|
|
812402526a | ||
|
|
322b0e1926 | ||
|
|
075ba32e99 | ||
|
|
0786f52259 | ||
|
|
d04f482da1 | ||
|
|
6df9903bc9 | ||
|
|
8ea3efb33a | ||
|
|
4255f95a12 | ||
|
|
b4dfeb2a09 | ||
|
|
a7fef8e6f1 | ||
|
|
735adeeac3 | ||
|
|
09879e9a4a | ||
|
|
d066b8b979 | ||
|
|
220d2bfc10 | ||
|
|
f0416cbb1f | ||
|
|
0fab14a138 | ||
|
|
c5d7f55543 | ||
|
|
a910950e45 | ||
|
|
37275d64fb | ||
|
|
a5866339b4 | ||
|
|
64d166fa7e | ||
|
|
4b37daa27a | ||
|
|
ed1364c21e | ||
|
|
0935f089e4 | ||
|
|
b20f111cbb | ||
|
|
38d6f14b95 | ||
|
|
c50e176e6c | ||
|
|
924cd98b5c | ||
|
|
a341917c7e | ||
|
|
3a86736040 | ||
|
|
5ac7ba79aa | ||
|
|
985f5ad0c9 | ||
|
|
8522a99dd6 | ||
|
|
3dedb5f21f | ||
|
|
eadb885126 | ||
|
|
e4cb8bfd5e | ||
|
|
43bbdc6f6c | ||
|
|
d022641ff2 | ||
|
|
787bec91cc | ||
|
|
7e6ebb205b | ||
|
|
23df24e0dd | ||
|
|
35c8ca8f82 | ||
|
|
75a6048ca4 | ||
|
|
69c8fabc68 | ||
|
|
7e59299731 | ||
|
|
44ca22a924 | ||
|
|
7a1a12d530 | ||
|
|
76b60c892a | ||
|
|
e37366c71a | ||
|
|
d3f859ab8e | ||
|
|
eac8c6b4d2 | ||
|
|
a3dc973d91 | ||
|
|
6b8c141e51 | ||
|
|
6b93915fb5 | ||
|
|
7d61511c32 | ||
|
|
7e6039f16a | ||
|
|
839aea3cfa | ||
|
|
f95a049c90 | ||
|
|
f659a1880f | ||
|
|
ed0890f9d2 | ||
|
|
6139208d0e | ||
|
|
cd3edb76fb | ||
|
|
6e4a804079 | ||
|
|
07781cfa63 | ||
|
|
fefac439c8 | ||
|
|
8ff8c7f34a | ||
|
|
cd38d8cb43 | ||
|
|
0801743ee0 | ||
|
|
20e6023c5e | ||
|
|
331ec61294 | ||
|
|
cf7401791e | ||
|
|
9227881d57 | ||
|
|
2b771fa30c | ||
|
|
51b612aed8 | ||
|
|
e7fa1bf25d | ||
|
|
53e305e9d3 | ||
|
|
564c650a28 | ||
|
|
4b74c69df4 | ||
|
|
61f50a8e61 | ||
|
|
befdbd75a4 | ||
|
|
10b45a9992 | ||
|
|
3bcd2d0b70 | ||
|
|
bfd29f02c4 | ||
|
|
01e7a90efd | ||
|
|
e3628c77b7 | ||
|
|
6dca79233c | ||
|
|
9d08ae6d33 | ||
|
|
19ebb2d6b6 | ||
|
|
46b93a0a5d | ||
|
|
4a7a02238b | ||
|
|
ed67514159 | ||
|
|
674af65789 | ||
|
|
454e428697 | ||
|
|
8ffd149d12 | ||
|
|
6c33c83033 | ||
|
|
8a521a5d43 | ||
|
|
c100fe828c | ||
|
|
6d7168caa4 | ||
|
|
993b1b20b7 | ||
|
|
56d3b6d53a | ||
|
|
4ddde1b2e9 | ||
|
|
c430dd8cae | ||
|
|
e8264aa348 | ||
|
|
4b009814f9 | ||
|
|
e5e75f9436 | ||
|
|
dd7840ffbd | ||
|
|
e93bd6b8aa | ||
|
|
3adf049c92 | ||
|
|
ece4e28731 | ||
|
|
21e1c63d0d | ||
|
|
a311e6ca03 | ||
|
|
bd5176db26 | ||
|
|
f5995941af | ||
|
|
80d0aa0996 | ||
|
|
0084b32f0f | ||
|
|
5f1889c753 | ||
|
|
e37c130cc0 | ||
|
|
29fa052ae9 | ||
|
|
df19eaaf9f | ||
|
|
ee5781df40 | ||
|
|
5ec5b42430 | ||
|
|
69dc7d638a | ||
|
|
71eafdecb0 | ||
|
|
534d00a975 | ||
|
|
c7a5363a75 | ||
|
|
e32a09bcd3 | ||
|
|
0f5bb01aec | ||
|
|
0c1ec3ce50 | ||
|
|
4e0023ec85 | ||
|
|
cb66894d3f | ||
|
|
328ebf9399 | ||
|
|
278ee8c44a | ||
|
|
815d896283 | ||
|
|
c86a66252d | ||
|
|
4518a455a8 | ||
|
|
9e3d8e5f39 | ||
|
|
4de86e2d61 | ||
|
|
b496fe07c2 | ||
|
|
c94fbff299 | ||
|
|
46e75a50ca | ||
|
|
5a91d9cbf0 | ||
|
|
32dbdf452c | ||
|
|
c019b57fde | ||
|
|
7797127879 | ||
|
|
5e4012965d | ||
|
|
3d697cadfc | ||
|
|
6402dedefa | ||
|
|
0b64edf79a | ||
|
|
d6bdbf08f9 | ||
|
|
31f935f1b9 | ||
|
|
4763b05981 | ||
|
|
bd767da106 | ||
|
|
a803e6c284 | ||
|
|
5e6e29cca9 | ||
|
|
5d70b05a67 | ||
|
|
c2a3f3c0ed | ||
|
|
ca398c7df8 | ||
|
|
9d76a84624 | ||
|
|
496940caa3 | ||
|
|
f527918672 | ||
|
|
92070b9c75 | ||
|
|
b650706f2f | ||
|
|
de271d25ef | ||
|
|
a9e52dc1e6 | ||
|
|
cb62a1f662 | ||
|
|
0c335a1a47 | ||
|
|
7ae38d5cf9 | ||
|
|
774a44d561 | ||
|
|
4d376505fd | ||
|
|
e1810b7188 | ||
|
|
348cf17068 | ||
|
|
defff755a3 | ||
|
|
33e4ff1c55 | ||
|
|
bd9cce0536 | ||
|
|
6846d45765 | ||
|
|
283cba2255 | ||
|
|
ff7954f500 | ||
|
|
d4f32d23a6 | ||
|
|
fd96ad4eeb | ||
|
|
54611a0a96 | ||
|
|
daf7152619 | ||
|
|
903559ca2a | ||
|
|
4190880b15 | ||
|
|
13eb99f410 | ||
|
|
c3798e7a29 | ||
|
|
fcb838fa9a | ||
|
|
29e3061fc7 | ||
|
|
cd9afa8c7e | ||
|
|
6f1ab4c1e0 | ||
|
|
76fd55d1d5 | ||
|
|
8325ce66f2 | ||
|
|
32e37f5bd4 | ||
|
|
a59a667a46 | ||
|
|
3ef9e724c4 | ||
|
|
bfb9649462 | ||
|
|
e7e8f3aad8 | ||
|
|
7dcdfbb06a | ||
|
|
df9cf9d44d | ||
|
|
a91952b796 | ||
|
|
5d00d87e18 | ||
|
|
6e0d3a2709 | ||
|
|
5d160f71ef | ||
|
|
d693b6d314 | ||
|
|
9e7be7ce01 | ||
|
|
67b7f09a6a | ||
|
|
c485317d8f | ||
|
|
c73add3bba | ||
|
|
4499df0b43 | ||
|
|
6cdb186f6d | ||
|
|
83305772e4 | ||
|
|
03f153c45b | ||
|
|
054be4f843 | ||
|
|
c51e7d2ac6 | ||
|
|
0ae51244ec | ||
|
|
c38f192aa9 | ||
|
|
f96355a239 | ||
|
|
5b1b870358 | ||
|
|
7fc47d72ee | ||
|
|
5496f1df45 | ||
|
|
ad529697e9 | ||
|
|
30d86ce06b | ||
|
|
7d0a5b1c89 | ||
|
|
56f9db57ef | ||
|
|
4f5adaab9b | ||
|
|
20622df1da | ||
|
|
49229e74d3 | ||
|
|
4679941755 | ||
|
|
498e8c24f5 | ||
|
|
2e04fe3164 | ||
|
|
002aabaeba | ||
|
|
fd0939df7f | ||
|
|
9f968554cb | ||
|
|
040481cdde | ||
|
|
76ab00b1c6 | ||
|
|
43b1b8e955 | ||
|
|
5435ffbed5 | ||
|
|
665f818f22 | ||
|
|
2ae7bb8d5a | ||
|
|
fe15155400 | ||
|
|
780f501941 | ||
|
|
d8c9347fea | ||
|
|
61a083658a | ||
|
|
668703d3f4 | ||
|
|
65eb41e01a | ||
|
|
163cdf68ff | ||
|
|
dc7634e385 | ||
|
|
ab01c7248d | ||
|
|
1f1381bd8b | ||
|
|
bca1e62368 | ||
|
|
a7305f66dc | ||
|
|
3bdf9850b9 | ||
|
|
b8525b762e | ||
|
|
05d9872bd7 | ||
|
|
5b995c9694 | ||
|
|
70ab147a3d | ||
|
|
822477f49a | ||
|
|
ede1b50b2c | ||
|
|
732d732027 | ||
|
|
f65abd6ff6 | ||
|
|
0aead0b14d | ||
|
|
1b3a08da0b | ||
|
|
d69d466651 | ||
|
|
a2e79d0962 | ||
|
|
caa096e79c | ||
|
|
fc3619a16d | ||
|
|
4304401960 | ||
|
|
e5a3d04ea2 | ||
|
|
0340e3dd83 | ||
|
|
aaa4f5e805 | ||
|
|
357d1b468f | ||
|
|
f8ce894ab6 | ||
|
|
61b5b091b9 | ||
|
|
7b0d9be8c1 | ||
|
|
9f1187962e | ||
|
|
cd5203b8f6 | ||
|
|
eb312084f1 | ||
|
|
6426cf266d | ||
|
|
774a7bd2b7 | ||
|
|
d7a39e9635 | ||
|
|
10a058967d | ||
|
|
a9763d5aab | ||
|
|
e21196906a | ||
|
|
e27b59283e | ||
|
|
4b0a9e50c3 | ||
|
|
140a7dc72b | ||
|
|
4b6920be1d | ||
|
|
f62e7b3dc9 | ||
|
|
9b8e26892f | ||
|
|
2d51971ff1 | ||
|
|
bf38f7d5c6 | ||
|
|
4dfe224ac1 | ||
|
|
908eea82f7 | ||
|
|
2c68486e08 | ||
|
|
862d885d21 | ||
|
|
a1056a5556 | ||
|
|
e7ccaf65d2 | ||
|
|
0c12dd7bc7 | ||
|
|
8d6834ac1f | ||
|
|
c04d31d778 | ||
|
|
fbcef69695 | ||
|
|
db64339ea6 | ||
|
|
d9cf7c8237 | ||
|
|
7c63dff032 | ||
|
|
6e1c9d42d3 | ||
|
|
b60261c1c1 | ||
|
|
d464813ed7 | ||
|
|
0a4b895e14 | ||
|
|
8a3c76231d | ||
|
|
4dc0d503b3 | ||
|
|
2511e26486 | ||
|
|
14628ba7e6 | ||
|
|
1c9d024b1e | ||
|
|
a1e0c487fe | ||
|
|
25bbf06444 | ||
|
|
09ef04565b | ||
|
|
18e40fa78e | ||
|
|
c464275763 | ||
|
|
fe6cffa6e4 | ||
|
|
e52432ec1a | ||
|
|
3a3d79624a | ||
|
|
ff818441f7 | ||
|
|
6893138df0 | ||
|
|
7c64006080 | ||
|
|
15e1f476ed | ||
|
|
328b101d05 | ||
|
|
ca0efb53dd | ||
|
|
0db815ba45 | ||
|
|
4b5b936a18 | ||
|
|
47c3ccda89 | ||
|
|
935e890db2 | ||
|
|
26be4af8a7 | ||
|
|
51ffa2449b | ||
|
|
8ee28c28e2 | ||
|
|
3c31586879 | ||
|
|
331a46e5ce | ||
|
|
7e96008168 | ||
|
|
91ab7b1861 | ||
|
|
e405207ea8 | ||
|
|
f23133e394 | ||
|
|
ce2eaa49fd | ||
|
|
dbf06fa9e5 | ||
|
|
a0417ad241 | ||
|
|
966e996ae0 | ||
|
|
0e3997eb0b | ||
|
|
2c3b420743 | ||
|
|
19ac59a26f | ||
|
|
4feea55788 | ||
|
|
8e386659e2 | ||
|
|
c8cdd1f2cf | ||
|
|
629855c2b7 | ||
|
|
7a5bb87b9e | ||
|
|
f7a9ab3be1 | ||
|
|
33ce4eba43 | ||
|
|
512a7e977f | ||
|
|
bc61b4520e | ||
|
|
f675b35cf6 | ||
|
|
ecca89df16 | ||
|
|
64e006c603 | ||
|
|
9bf4933ec6 | ||
|
|
55200f6bbe | ||
|
|
5331ceea99 | ||
|
|
f0c6b07c66 | ||
|
|
15508345ca | ||
|
|
a3b4937469 | ||
|
|
3860669bfe | ||
|
|
8c3ca0e3a5 | ||
|
|
ca4ddc283f | ||
|
|
316da899e7 | ||
|
|
b6dd03ce6a | ||
|
|
30af5939ba | ||
|
|
ce145f8215 | ||
|
|
9e97c0c32b | ||
|
|
8c5a8d78cf | ||
|
|
b2b9a8c2f9 | ||
|
|
77e686f97d | ||
|
|
dff9671f74 | ||
|
|
71cac1cb38 | ||
|
|
06dd7b4aa6 | ||
|
|
5808380440 | ||
|
|
a562733d9f | ||
|
|
3d13c78896 | ||
|
|
c230556d9b | ||
|
|
4b1af9f589 | ||
|
|
f2aca21e9a | ||
|
|
146db7a84f | ||
|
|
f687b4f19a | ||
|
|
155a9a06c3 | ||
|
|
27588b2b74 | ||
|
|
f6243d164c | ||
|
|
5f647da1ac | ||
|
|
06f177031b | ||
|
|
fad68b78dc | ||
|
|
02c916c11b | ||
|
|
eea0ed6cdb | ||
|
|
2caa12d4af | ||
|
|
8ddaa2c95d | ||
|
|
1c6c515e03 | ||
|
|
6f91c8892f | ||
|
|
b8de7d7da7 | ||
|
|
64c3285b5d | ||
|
|
3571c8947c | ||
|
|
1324f775d0 | ||
|
|
5617ed1e82 | ||
|
|
ff5c8bc777 | ||
|
|
326fc96371 | ||
|
|
2a3a7ffa81 | ||
|
|
795cd6ee96 | ||
|
|
b1f9e44746 | ||
|
|
b42609e0a0 | ||
|
|
4b4bbdc080 | ||
|
|
1bebf0ddc2 | ||
|
|
f9490379cc | ||
|
|
90734285f2 | ||
|
|
01ca01eecf | ||
|
|
e88166b64d | ||
|
|
62cd9b8ef4 | ||
|
|
5e6b3b4f87 | ||
|
|
1e091de9b3 | ||
|
|
156b9da2d3 | ||
|
|
c04d345970 | ||
|
|
a61eb69a0f | ||
|
|
d26720a9c2 | ||
|
|
d4c01061aa | ||
|
|
ea134948f6 | ||
|
|
e3870ec10a | ||
|
|
555d46e623 | ||
|
|
f778132175 | ||
|
|
4dbc0f3b54 | ||
|
|
80b6bddd65 | ||
|
|
bcd7743073 | ||
|
|
553fdef352 | ||
|
|
74948cd917 | ||
|
|
c6c884b232 | ||
|
|
e8fd0d9953 | ||
|
|
83bfb64d49 | ||
|
|
e0e6731d4f | ||
|
|
741a389ebd | ||
|
|
169378ff01 | ||
|
|
d96b05a2aa | ||
|
|
affc20bf9f | ||
|
|
e3fe8db5f4 | ||
|
|
282fd732f1 | ||
|
|
0d3b0733d2 | ||
|
|
599e4b40d1 | ||
|
|
eb6a8777a0 | ||
|
|
11845fd598 | ||
|
|
4a8a953247 | ||
|
|
c480c4d66a | ||
|
|
30c1b4414b | ||
|
|
886e026d17 | ||
|
|
6c60f90518 | ||
|
|
2b6b25bf80 | ||
|
|
3d70bfac4c | ||
|
|
18e22b4f1e | ||
|
|
356358f011 | ||
|
|
e93bcc02b1 | ||
|
|
fd96d805af | ||
|
|
a69ea709a3 | ||
|
|
163336bc0f | ||
|
|
4aac987725 | ||
|
|
11a93fa7e3 | ||
|
|
e4690f1235 | ||
|
|
328477628d | ||
|
|
a520e17de1 | ||
|
|
35b0bf57a7 | ||
|
|
bf3ba5c6d8 | ||
|
|
a6b5e94b24 | ||
|
|
0b60ff67ce | ||
|
|
80e1a2b9ca | ||
|
|
a235b772b4 | ||
|
|
c9b64db2bf | ||
|
|
61ad4fdab2 | ||
|
|
ef325d3b49 | ||
|
|
6039251df3 | ||
|
|
51f790cd62 | ||
|
|
662f61b437 | ||
|
|
ace4a53641 | ||
|
|
b2b9d8c818 | ||
|
|
d79ff003ca | ||
|
|
9e46a815cf | ||
|
|
4b6e5839ba | ||
|
|
e6a87a6c04 | ||
|
|
db575f5bc0 | ||
|
|
e51aecbba8 | ||
|
|
3d55a709f0 | ||
|
|
9a748cd008 | ||
|
|
8312df445d | ||
|
|
db07de59f9 | ||
|
|
c310b60eca | ||
|
|
e27526c635 | ||
|
|
b0c687d0ad | ||
|
|
504a92cb43 | ||
|
|
65790cbb02 | ||
|
|
281b8d0565 | ||
|
|
64f799102f | ||
|
|
f35c05cc12 | ||
|
|
aeccd787f0 | ||
|
|
2260462017 | ||
|
|
01f1009473 | ||
|
|
7146014b0f | ||
|
|
e3752d3f08 | ||
|
|
1b729145fe | ||
|
|
5a5b3a287a | ||
|
|
84de8d99f1 | ||
|
|
2dc1515d48 | ||
|
|
c5f7ff602d | ||
|
|
7e03391514 | ||
|
|
7dff488a44 | ||
|
|
0d7eea6356 | ||
|
|
d5325f59e5 | ||
|
|
3d63153d66 | ||
|
|
a2139b3ad4 | ||
|
|
fcf3be65be | ||
|
|
2ac0f00d00 | ||
|
|
5fdbc830b9 | ||
|
|
b96b200c47 | ||
|
|
4b4f101369 | ||
|
|
2a4b54f6c6 | ||
|
|
df99febd5f | ||
|
|
6104d52803 | ||
|
|
fc67916525 | ||
|
|
4ea86a221e | ||
|
|
fe97b5c31f | ||
|
|
e63ca32171 | ||
|
|
b5eb216860 | ||
|
|
7e794dc2dc | ||
|
|
7c51add1a1 | ||
|
|
3e809a4e7d | ||
|
|
417024ce88 | ||
|
|
a88818c0d8 | ||
|
|
a020d44b5c | ||
|
|
f4268d781a | ||
|
|
e5a7ae7182 | ||
|
|
edfb3acea7 | ||
|
|
d3d7e44f2e | ||
|
|
5134ceb766 | ||
|
|
0e65949997 | ||
|
|
a58675074a | ||
|
|
859433eee7 | ||
|
|
83f33f24ec | ||
|
|
f3d2f96181 | ||
|
|
3df1b09ac6 | ||
|
|
fbf8a5c257 | ||
|
|
0ab62a2a65 | ||
|
|
7655b2c96f | ||
|
|
1e345f4ca1 | ||
|
|
6c05584404 | ||
|
|
10c0d7bea9 | ||
|
|
891d9f40c1 | ||
|
|
a516884a65 |
13
.gitignore
vendored
13
.gitignore
vendored
@ -10,3 +10,16 @@ src/server/log/
|
||||
src/server/*.exe
|
||||
src/server/gamedata/config/*.json
|
||||
src/server/unit_test.go
|
||||
src/server/teLog/*
|
||||
src/server/teLog/log.2024-11-28
|
||||
src/server/logs/ga_log/*.log
|
||||
src/server/goroutine.prof
|
||||
src/server/heap_after.pb.gz
|
||||
src/server/test/logs/*
|
||||
src/server/test/teLog/*
|
||||
src/server/*.exe*
|
||||
src/server/msg/Gameapi.pb.go
|
||||
src/server/gen-go
|
||||
src/server/GeoLite2-Country
|
||||
src/server/test/GeoLite2-Country
|
||||
src/server/msg/Gameapi_grpc.pb.go
|
||||
|
||||
@ -1,179 +0,0 @@
|
||||
package GoUtil
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/gob"
|
||||
"math/rand"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 实例化一个通过字符串映射函数切片的map
|
||||
var eventByName = make(map[string][]*EventObj)
|
||||
|
||||
type EventObj struct {
|
||||
Callback func([]interface{})
|
||||
Obj interface{}
|
||||
}
|
||||
|
||||
func (o *EventObj) isEqual(tar *EventObj) bool {
|
||||
if reflect.ValueOf(o.Callback).Pointer() == reflect.ValueOf(tar.Callback).Pointer() && o.Obj == tar.Obj {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// 注册事件,提供事件名和回调函数
|
||||
func RegisterEvent(name string, callback func([]interface{}), Obj interface{}) {
|
||||
|
||||
eo := new(EventObj)
|
||||
eo.Callback = callback
|
||||
eo.Obj = Obj
|
||||
// 通过名字查找事件列表
|
||||
list := eventByName[name]
|
||||
|
||||
// 在列表切片中添加函数
|
||||
list = append(list, eo)
|
||||
|
||||
// 将修改的事件列表切片保存回去
|
||||
eventByName[name] = list
|
||||
}
|
||||
|
||||
// 调用事件
|
||||
func CallEvent(name string, param []interface{}) {
|
||||
|
||||
// 通过名字找到事件列表
|
||||
list := eventByName[name]
|
||||
|
||||
// 遍历这个事件的所有回调
|
||||
for _, eo := range list {
|
||||
// 传入参数调用回调
|
||||
eo.Callback(param)
|
||||
}
|
||||
}
|
||||
|
||||
func RemoveEvent(name string, callback func([]interface{}), Obj interface{}) {
|
||||
// 通过名字找到事件列表
|
||||
list := eventByName[name]
|
||||
j := 0
|
||||
eo := new(EventObj)
|
||||
eo.Callback = callback
|
||||
eo.Obj = Obj
|
||||
// 遍历这个事件的所有回调
|
||||
for _, v := range list {
|
||||
if !v.isEqual(eo) {
|
||||
list[j] = v
|
||||
j++
|
||||
}
|
||||
}
|
||||
eventByName[name] = list[:j]
|
||||
// fmt.Println("len eventByName[name]:", len(eventByName[name]))
|
||||
//fmt.Println("len eventByName[name]:", len(eventByName))
|
||||
// fmt.Println("len list:", len(list))
|
||||
}
|
||||
|
||||
func DeleteEleByValue(list []int, ele int) []int {
|
||||
j := 0
|
||||
for _, v := range list {
|
||||
if v != ele {
|
||||
list[j] = v
|
||||
j++
|
||||
}
|
||||
}
|
||||
ret := list[:j]
|
||||
return ret
|
||||
}
|
||||
|
||||
func BoolToInt32(b bool) int32 {
|
||||
if b {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func IfTrue(a bool, b, c interface{}) interface{} {
|
||||
if a {
|
||||
return b
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func Int64(a interface{}) int64 {
|
||||
if a == nil {
|
||||
return 0
|
||||
}
|
||||
switch v := a.(type) {
|
||||
case int:
|
||||
return int64(v)
|
||||
case int32:
|
||||
return int64(v)
|
||||
case int64:
|
||||
return v
|
||||
case float64:
|
||||
return int64(v)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func Int(a interface{}) int {
|
||||
if a == nil {
|
||||
return 0
|
||||
}
|
||||
switch v := a.(type) {
|
||||
case int:
|
||||
return v
|
||||
case int32:
|
||||
return int(v)
|
||||
case int64:
|
||||
return int(v)
|
||||
case float64:
|
||||
return int(v)
|
||||
case string:
|
||||
r, err := strconv.Atoi(v)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return r
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func GobMarshal(data interface{}) ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
encode := gob.NewEncoder(&buf)
|
||||
err := encode.Encode(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
func GobUnmarshal(data []byte, obj interface{}) error {
|
||||
decode := gob.NewDecoder(bytes.NewReader(data))
|
||||
err := decode.Decode(obj)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetServerIdByUid(uid int) int {
|
||||
return int(uid / 100000)
|
||||
}
|
||||
|
||||
func CreateOrderSn(uid int) string {
|
||||
Now := time.Now()
|
||||
return "order_" + strconv.Itoa(uid) + "_" + Now.Format("20060102150405") + RandString(6)
|
||||
}
|
||||
|
||||
// 生成指定长度的随机字符串
|
||||
func RandString(n int) string {
|
||||
const letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
b := make([]byte, n)
|
||||
for i := range b {
|
||||
b[i] = letters[r.Intn(len(letters))]
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
@ -1,8 +0,0 @@
|
||||
package GoUtil
|
||||
|
||||
func RandNum(start int, end int) int {
|
||||
if start > end {
|
||||
return 0
|
||||
}
|
||||
return start + GetRand().Intn(end-start+1)
|
||||
}
|
||||
@ -1,172 +0,0 @@
|
||||
package GoUtil
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func IntToInt32(d []int) []int32 {
|
||||
r := make([]int32, 0, len(d))
|
||||
for _, d := range d {
|
||||
r = append(r, int32(d))
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func RandPopSlice(slice []int) ([]int, int) {
|
||||
slen := len(slice)
|
||||
if slen == 0 {
|
||||
return slice, -1
|
||||
}
|
||||
Id := GetRand().Intn(slen)
|
||||
return append(slice[0:Id], slice[Id+1:]...), slice[Id]
|
||||
}
|
||||
|
||||
func RandSlice(slice []int) int {
|
||||
slen := len(slice)
|
||||
if slen == 0 {
|
||||
return 0
|
||||
}
|
||||
Id := GetRand().Intn(slen)
|
||||
return slice[Id]
|
||||
}
|
||||
|
||||
func RandSliceNum(slice []int, num int) []int {
|
||||
r := make([]int, 0, num)
|
||||
if num <= 0 || len(slice) < num {
|
||||
return slice
|
||||
}
|
||||
|
||||
for i := 0; i < num; i++ {
|
||||
Id := GetRand().Intn(len(slice))
|
||||
r = append(r, slice[Id])
|
||||
slice = append(slice[0:Id], slice[Id+1:]...)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func RandSliceNumNonAdjacent(slice []int, num int) []int {
|
||||
if len(slice) < 2*num {
|
||||
return nil
|
||||
}
|
||||
sort.Ints(slice)
|
||||
result := make([]int, 0, num)
|
||||
for len(result) < num {
|
||||
Id := GetRand().Intn(len(slice))
|
||||
result = append(result, slice[Id])
|
||||
slice = SubAdjacentElemSlice(slice, Id)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func SubAdjacentElemSlice(s []int, Id int) []int {
|
||||
r := make([]int, 0, len(s))
|
||||
for k, v := range s {
|
||||
if k < Id-1 || k > Id+1 {
|
||||
r = append(r, v)
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func RandStringSlice(slice []string) string {
|
||||
slen := len(slice)
|
||||
if slen == 0 {
|
||||
return ""
|
||||
}
|
||||
Id := GetRand().Intn(slen)
|
||||
return slice[Id]
|
||||
}
|
||||
|
||||
func SliceStringToInt(s []string) []int {
|
||||
if len(s) == 0 {
|
||||
return []int{}
|
||||
}
|
||||
r := make([]int, 0, len(s))
|
||||
for _, v := range s {
|
||||
v1, _ := strconv.Atoi(v)
|
||||
r = append(r, v1)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func SliceIntToInt32(s []int) []int32 {
|
||||
r := make([]int32, 0, len(s))
|
||||
for _, v := range s {
|
||||
r = append(r, int32(v))
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func PopElemSlice(s []int, Id int) ([]int, bool) {
|
||||
for k, v := range s {
|
||||
if v == Id {
|
||||
return append(s[0:k], s[k+1:]...), true
|
||||
}
|
||||
}
|
||||
return s, false
|
||||
}
|
||||
|
||||
func ElemInSlice(s []int, Id int) bool {
|
||||
for _, v := range s {
|
||||
if v == Id {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func GetElemNum(s []int, Id int) int {
|
||||
n := 0
|
||||
for _, v := range s {
|
||||
if v == Id {
|
||||
n++
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func InArray(Id int, s []int) bool {
|
||||
for _, v := range s {
|
||||
if v == Id {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func InStringArray(Id string, s []string) bool {
|
||||
for _, v := range s {
|
||||
if v == Id {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// toInterfaceSlice converts a slice of strings to a slice of empty interfaces
|
||||
func ToInterfaceSlice(slice []string) []interface{} {
|
||||
result := make([]interface{}, len(slice))
|
||||
for i, v := range slice {
|
||||
result[i] = v
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// a - b
|
||||
func SubSlices(a, b []int) []int {
|
||||
result := make([]int, 0, len(a))
|
||||
for _, num := range a {
|
||||
if !InArray(num, b) {
|
||||
result = append(result, num)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func PopSlice(s []int) (int, []int) {
|
||||
if len(s) == 0 {
|
||||
return -1, s
|
||||
}
|
||||
return s[0], s[1:]
|
||||
}
|
||||
@ -3,13 +3,19 @@ package MergeConst
|
||||
type ProtocolType int32
|
||||
|
||||
const (
|
||||
Protocol_Error_Account_Exist int32 = 100
|
||||
Protocol_Error_Account_OR_PWD_ERROR int32 = 101
|
||||
Protocol_Error_Account_OR_PWD_Short int32 = 102
|
||||
Protocol_Error_Account_Fail int32 = 103
|
||||
Protocol_Error_Account_NoExsit int32 = 104
|
||||
Protocol_Res_Buy_Cnt_Limit int32 = 110
|
||||
Protocol_Res_Buy_CD int32 = 111
|
||||
Protocol_Error_Account_Exist int32 = 100
|
||||
Protocol_Error_Account_OR_PWD_ERROR int32 = 101
|
||||
Protocol_Error_Account_OR_PWD_Short int32 = 102
|
||||
Protocol_Error_Account_Fail int32 = 103
|
||||
Protocol_Error_Account_NoExsit int32 = 104
|
||||
Protocol_Error_Account_Code_Error int32 = 105
|
||||
Protocol_Error_Account_Device_Error int32 = 106
|
||||
Protocol_Error_Id_Not_Verify int32 = 107
|
||||
Protocol_Error_Id_Verify_Error int32 = 108
|
||||
Protocol_Error_Account_Ban int32 = 109
|
||||
Protocol_Res_Buy_Cnt_Limit int32 = 110
|
||||
Protocol_Res_Buy_CD int32 = 111
|
||||
|
||||
Protocol_Email_Find_Fail int32 = 120
|
||||
Protocol_Active_No_Exsit int32 = 130
|
||||
Protocol_Active_7Day_Rewarded int32 = 131
|
||||
@ -94,10 +100,12 @@ const G_Champion_settlement_Duration = 3600 * 23
|
||||
const G_Champion_Unlock_Score = 2
|
||||
const G_Champion_Max_Score = 44650
|
||||
const G_Champion_People_Cnt = 50
|
||||
|
||||
const SUCCESS = 1
|
||||
const (
|
||||
ORDER_STATUS_IDLE = 0 // 订单未完成
|
||||
ORDER_STATUS_PAY = 1 // 订单已支付
|
||||
ORDER_STATUS_CANCLE = 2 // 订单取消
|
||||
ORDER_STATUS_CANCEL = 2 // 订单取消
|
||||
ORDER_STATUS_SHIP = 3 // 订单已发货
|
||||
)
|
||||
|
||||
const GLOBAL_SERVER_ID = 0 // 全局服ID
|
||||
|
||||
8
src/server/MergeConst/system.go
Normal file
8
src/server/MergeConst/system.go
Normal file
@ -0,0 +1,8 @@
|
||||
package MergeConst
|
||||
|
||||
const (
|
||||
Go_gc_percent = 200
|
||||
Go_gc_memory_limit = 1024 << 20
|
||||
Go_game_version = "1.0.3" // 游戏版本号,格式为 "主版本号.次版本号.修订号",每次发布新版本时需要更新
|
||||
Go_log_delete_days = 3 // 日志删除天数,超过这个天数的日志文件将被删除
|
||||
)
|
||||
16
src/server/README.MD
Normal file
16
src/server/README.MD
Normal file
@ -0,0 +1,16 @@
|
||||
## 命名规范
|
||||
|
||||
|
||||
- **清晰优先**:名称应准确表达含义,避免歧义。
|
||||
- **导出规则**:导出标识符首字母大写,未导出首字母小写。
|
||||
- **包名**:小写单词,简短且描述职责(如 `store`、`auth`)。
|
||||
- **文件名**:小写(可下划线分隔),测试文件以 `_test.go` 结尾。
|
||||
- **函数/变量/类型**:驼峰命名;导出使用 PascalCase(例如 `UserService`、`CreateUser`)。
|
||||
- **接口**:以行为命名,常用 `-er` 结尾(如 `Reader`、`Store`),避免 `I` 前缀。
|
||||
- **缩写**:统一大小写(例如导出使用 `ID`、`URL`;未导出使用 `id`、`url`)。
|
||||
- **错误**:包级错误使用 `Err` 前缀(如 `ErrNotFound`)。
|
||||
- **Context 与并发**:统一使用 `ctx` 作 `context.Context`,通道命名要有语义(如 `done`, `jobs`)。
|
||||
- **构造函数/选项**:使用 `NewType` 与 `WithXxx` 约定,避免多个布尔参数。
|
||||
|
||||
|
||||
|
||||
78
src/server/backend/server.go
Normal file
78
src/server/backend/server.go
Normal file
@ -0,0 +1,78 @@
|
||||
package backend
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"server/conf"
|
||||
"server/game"
|
||||
"server/msg"
|
||||
|
||||
"gitea.bywaystudios.com/pet_home/leaf/log"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
type backendServer struct {
|
||||
msg.UnimplementedBackendServer
|
||||
}
|
||||
|
||||
func (s *backendServer) ReloadActivity(ctx context.Context, req *msg.ReqActivityCfgReload) (*msg.ResActivityCfgReload, error) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
log.Error("ReloadActivity panic: %v", r)
|
||||
}
|
||||
}()
|
||||
log.Debug("Received ReloadActivity request: %v", req)
|
||||
game.AcitivityCfgReload()
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (s *backendServer) OrderShipping(ctx context.Context, req *msg.ReqOrderShipping) (*msg.ResOrderShipping, error) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
log.Error("OrderShipping panic: %v", r)
|
||||
}
|
||||
}()
|
||||
log.Debug("Received OrderShipping request: %v", req)
|
||||
res, err := game.AdminShipping(req)
|
||||
if err != nil {
|
||||
log.Error("OrderShipping error: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (s *backendServer) UserDetail(ctx context.Context, req *msg.UserDetailParam) (*msg.ResUserDetail, error) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
log.Error("UserDetail panic: %v", r)
|
||||
}
|
||||
}()
|
||||
log.Debug("Received UserDetail request: %v", req)
|
||||
res, err := game.AdminPlayerDetailInfo(req)
|
||||
if err != nil {
|
||||
log.Error("UserDetail error: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func Start() {
|
||||
if conf.Server.RPCAddr == "" {
|
||||
log.Debug("RPC server address not configured, skipping gRPC server startup")
|
||||
return
|
||||
}
|
||||
lis, err := net.Listen("tcp", conf.Server.RPCAddr)
|
||||
if err != nil {
|
||||
log.Error("failed to listen: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
s := grpc.NewServer()
|
||||
msg.RegisterBackendServer(s, &backendServer{})
|
||||
|
||||
log.Debug("gRPC server listening on %s", conf.Server.RPCAddr)
|
||||
if err := s.Serve(lis); err != nil {
|
||||
log.Error("server exited with error: %v", err)
|
||||
}
|
||||
}
|
||||
@ -2,8 +2,9 @@ package base
|
||||
|
||||
import (
|
||||
"server/conf"
|
||||
"server/pkg/github.com/name5566/leaf/chanrpc"
|
||||
"server/pkg/github.com/name5566/leaf/module"
|
||||
|
||||
"gitea.bywaystudios.com/pet_home/leaf/chanrpc"
|
||||
"gitea.bywaystudios.com/pet_home/leaf/module"
|
||||
)
|
||||
|
||||
func NewSkeleton() *module.Skeleton {
|
||||
|
||||
113
src/server/benchmark_test.go
Normal file
113
src/server/benchmark_test.go
Normal file
@ -0,0 +1,113 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"server/game"
|
||||
"server/game/mod/msg"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// func TestBenchInit(t *testing.T) {
|
||||
// f := "wmz00%d"
|
||||
// for i := 0; i < 10000; i++ {
|
||||
// UserName := fmt.Sprintf(f, i)
|
||||
// game.G_GameLogicPtr.Db_AccountInfo.UserName = UserName
|
||||
// game.G_GameLogicPtr.Db_AccountInfo.UserPassword = "123456"
|
||||
// if game.G_GameLogicPtr.NewAccountInsertDataToDB() {
|
||||
// fmt.Printf("UserName:%s\n init success", UserName)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
/*
|
||||
*
|
||||
cluster 消息处理基准测试
|
||||
|
||||
36716 34961 ns/op 1690 B/op 38 allocs/op
|
||||
*/
|
||||
func BenchmarkClusterMsg(b *testing.B) {
|
||||
game.ClusterMgrInit()
|
||||
runtime.GOMAXPROCS(8)
|
||||
game.G_getGameLogic()
|
||||
for i := 0; i < b.N; i++ {
|
||||
m := &msg.Msg{
|
||||
HandleType: msg.HANDLE_MOD_PLAYER_LOGIN,
|
||||
Extra: 0,
|
||||
}
|
||||
game.MessageHandle(m)
|
||||
}
|
||||
}
|
||||
|
||||
func printMemUsage() {
|
||||
var m runtime.MemStats
|
||||
runtime.ReadMemStats(&m)
|
||||
// 输出内存使用情况
|
||||
fmt.Printf("Alloc = %v MiB", bToMb(m.Alloc))
|
||||
fmt.Printf("\tTotalAlloc = %v MiB", bToMb(m.TotalAlloc))
|
||||
fmt.Printf("\tSys = %v MiB", bToMb(m.Sys))
|
||||
fmt.Printf("\tNumGC = %v\n", m.NumGC)
|
||||
var playerCount int
|
||||
game.G_GameLogicPtr.M_Players.Range(func(key, value interface{}) bool {
|
||||
playerCount++
|
||||
return true
|
||||
})
|
||||
fmt.Printf("\tPlayerNum = %v\n", playerCount)
|
||||
}
|
||||
|
||||
func bToMb(b uint64) uint64 {
|
||||
return b / 1024 / 1024
|
||||
}
|
||||
|
||||
func BenchmarkChampionshipGroup(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
game.G_GameLogicPtr.CreateChampshipMgr()
|
||||
game.G_GameLogicPtr.ChampshipMgr.Debug()
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkPlayerInit(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
p := new(game.Player)
|
||||
p.InitPlayer("3625212")
|
||||
p.LoginBackData()
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkPlayerBackup(b *testing.B) {
|
||||
p := new(game.Player)
|
||||
p.InitPlayer("3625212")
|
||||
for i := 0; i < b.N; i++ {
|
||||
p.BackUp()
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkPlayerRecover(b *testing.B) {
|
||||
p := new(game.Player)
|
||||
p.InitPlayer("3625212")
|
||||
backup := p.BackUp()
|
||||
for i := 0; i < b.N; i++ {
|
||||
p.Recover(backup)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkPlayerHandleMsg(b *testing.B) {
|
||||
p := new(game.Player)
|
||||
p.InitPlayer("3625212")
|
||||
list := make([]*msg.Msg, 0, 1000)
|
||||
for i := 0; i < 1000; i++ {
|
||||
m := &msg.Msg{
|
||||
HandleType: msg.HANDLE_MOD_PLAYER_LOGIN,
|
||||
Type: msg.HANDLE_TYPE_APPLY,
|
||||
From: 100001,
|
||||
To: i + 100002,
|
||||
Extra: 0,
|
||||
}
|
||||
list = append(list, m)
|
||||
}
|
||||
for i := 0; i < b.N; i++ {
|
||||
for _, m := range list {
|
||||
p.HandleMsg(m)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3,12 +3,14 @@ package mergeCluster
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"server/GoUtil"
|
||||
"server/conf"
|
||||
"server/game/mod/msg"
|
||||
"server/pkg/github.com/name5566/leaf/log"
|
||||
"server/pkg/github.com/name5566/leaf/network"
|
||||
GoUtil "server/game_util"
|
||||
"sync"
|
||||
|
||||
"gitea.bywaystudios.com/pet_home/leaf/network"
|
||||
|
||||
"gitea.bywaystudios.com/pet_home/leaf/log"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -16,7 +18,9 @@ const (
|
||||
)
|
||||
|
||||
var FuncMap = map[int]func(*Agent, *msg.Msg) error{} // 消息处理函数
|
||||
|
||||
var funcMapMu sync.RWMutex // FuncMap 的读写锁
|
||||
var CallbackChan = make(map[string]chan *msg.Msg) // 回调消息队列
|
||||
var callbackChanMu sync.RWMutex // CallbackChan 的读写锁
|
||||
var (
|
||||
server *network.TCPServer // 服务器
|
||||
Center *network.TCPClient // 集群中心
|
||||
@ -30,14 +34,14 @@ func Init() {
|
||||
server = new(network.TCPServer)
|
||||
server.Addr = conf.Server.ListenAddr
|
||||
server.MaxConnNum = int(math.MaxInt32)
|
||||
server.PendingWriteNum = conf.PendingWriteNum
|
||||
server.PendingWriteNum = 1 << 14
|
||||
server.LenMsgLen = 4
|
||||
server.MaxMsgLen = 4096
|
||||
server.MaxMsgLen = 1 << 16
|
||||
server.NewAgent = newServerAgent
|
||||
server.Start()
|
||||
}
|
||||
|
||||
if conf.Server.CenterAddr != "" {
|
||||
if conf.Server.CenterAddr != "" && conf.Server.ServerType != "center" {
|
||||
connectRemote(conf.Server.CenterAddr, ClusterCenterId, "center")
|
||||
}
|
||||
|
||||
@ -47,6 +51,11 @@ func Init() {
|
||||
registerFunc(msg.CLUSTER_EXIT, ClusterExit)
|
||||
}
|
||||
|
||||
// GetCallbackChanMu 返回 CallbackChan 的读写锁,供外部包安全访问 CallbackChan
|
||||
func GetCallbackChanMu() *sync.RWMutex {
|
||||
return &callbackChanMu
|
||||
}
|
||||
|
||||
func Destroy() {
|
||||
if server != nil {
|
||||
log.Release("closing cluster server")
|
||||
@ -88,7 +97,7 @@ func (a *Agent) Run() {
|
||||
m := msg.Msg{}
|
||||
err = GoUtil.GobUnmarshal(data, &m)
|
||||
if err != nil {
|
||||
log.Debug("decode err: %v", err)
|
||||
log.Debug("decode err: %v, data: %s", err, string(data))
|
||||
return
|
||||
}
|
||||
err = processMsg(a, &m)
|
||||
|
||||
@ -2,12 +2,14 @@ package mergeCluster
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"server/GoUtil"
|
||||
"server/conf"
|
||||
"server/game/mod/msg"
|
||||
"server/pkg/github.com/name5566/leaf/log"
|
||||
"server/pkg/github.com/name5566/leaf/network"
|
||||
GoUtil "server/game_util"
|
||||
"time"
|
||||
|
||||
"gitea.bywaystudios.com/pet_home/leaf/network"
|
||||
|
||||
"gitea.bywaystudios.com/pet_home/leaf/log"
|
||||
)
|
||||
|
||||
func RevcServerMsg(m *msg.Msg) error {
|
||||
@ -48,19 +50,14 @@ func HandShakeRecv(a *Agent, m *msg.Msg) error {
|
||||
RemoteAddr: m.Extra.(string),
|
||||
},
|
||||
})
|
||||
} else {
|
||||
syncMsg := &msg.Msg{
|
||||
Type: msg.CLUSTER_FRIEND_SYNC,
|
||||
To: ServerId,
|
||||
HandleType: msg.HANDLE_MOD_CLUSTER_SYNC,
|
||||
}
|
||||
sendGameMsg(syncMsg)
|
||||
}
|
||||
syncMsg := &msg.Msg{
|
||||
Type: msg.CLUSTER_FRIEND_SYNC,
|
||||
To: ServerId,
|
||||
}
|
||||
sendGameMsg(syncMsg)
|
||||
fmt.Print("现有区服连接:")
|
||||
serverAgent.Range(func(key, value interface{}) bool {
|
||||
fmt.Print(key)
|
||||
fmt.Print(",")
|
||||
return true
|
||||
})
|
||||
fmt.Println()
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -79,7 +76,7 @@ func ClusterJoin(a *Agent, m *msg.Msg) error {
|
||||
return nil
|
||||
}
|
||||
log.Debug("ClusterJoin ServerId %v", clusterJoin.ServerId)
|
||||
connectRemote(clusterJoin.RemoteAddr, clusterJoin.ServerId, "server")
|
||||
//connectRemote(clusterJoin.RemoteAddr, clusterJoin.ServerId, "server")
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -96,23 +93,30 @@ func connectRemote(RemoteAddr string, ConnType int, ConnLabel string) error {
|
||||
client := new(network.TCPClient)
|
||||
client.Addr = RemoteAddr
|
||||
client.ConnNum = 1
|
||||
client.PendingWriteNum = conf.PendingWriteNum
|
||||
client.PendingWriteNum = 1 << 14
|
||||
client.LenMsgLen = 4
|
||||
client.MaxMsgLen = 4096
|
||||
client.MaxMsgLen = 1 << 16
|
||||
client.NewAgent = newAgent
|
||||
client.ConnType = ConnType
|
||||
client.ConnLabel = ConnLabel
|
||||
client.ConnectInterval = time.Duration(time.Minute * 5)
|
||||
client.ConnectInterval = time.Duration(time.Minute * 1)
|
||||
if ConnType == ClusterCenterId { // 中心服断开重连
|
||||
client.AutoReconnect = true
|
||||
}
|
||||
client.Start()
|
||||
Center = client
|
||||
clients = append(clients, client)
|
||||
log.Debug("connet remote to addr:%s", RemoteAddr)
|
||||
return nil
|
||||
}
|
||||
|
||||
func SendServerMsg(m *msg.Msg, serverId int) error {
|
||||
if m.UniKey == "" {
|
||||
m.UniKey = GoUtil.UniKey(fmt.Sprintf("%v,Cluster Msg", m))
|
||||
}
|
||||
if m.SendT == 0 {
|
||||
m.SendT = GoUtil.Now()
|
||||
}
|
||||
if v, ok := serverAgent.Load(serverId); ok {
|
||||
data, err := GoUtil.GobMarshal(m)
|
||||
if err != nil {
|
||||
@ -120,10 +124,47 @@ func SendServerMsg(m *msg.Msg, serverId int) error {
|
||||
return err
|
||||
}
|
||||
v.(network.Agent).WriteMsg(data)
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("server %d not online", serverId)
|
||||
}
|
||||
|
||||
func CallServerMsg(m *msg.Msg, serverId int) (*msg.Msg, error) {
|
||||
if m.UniKey == "" {
|
||||
m.UniKey = GoUtil.UniKey(fmt.Sprintf("%v,Cluster Msg", m))
|
||||
}
|
||||
if m.SendT == 0 {
|
||||
m.SendT = GoUtil.Now()
|
||||
}
|
||||
v, ok := serverAgent.Load(serverId)
|
||||
// 之后再发送消息
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("server %d not online", serverId)
|
||||
}
|
||||
// 先注册回调通道,避免发送出去后对方快速返回导致丢失
|
||||
newChan := make(chan *msg.Msg, 1)
|
||||
registerChanel(m.UniKey, newChan)
|
||||
defer unregisterChanel(m.UniKey)
|
||||
data, err := GoUtil.GobMarshal(m)
|
||||
if err != nil {
|
||||
log.Debug("CallServerMsg GobMarshal err %v", err)
|
||||
return nil, err
|
||||
}
|
||||
v.(network.Agent).WriteMsg(data)
|
||||
// 等待返回(直接接收一次)
|
||||
timeout := time.After(5 * time.Second)
|
||||
select {
|
||||
case backm := <-newChan:
|
||||
if backm == nil {
|
||||
return nil, fmt.Errorf("server %d not response", serverId)
|
||||
}
|
||||
// log.Debug("CallServerMsg reply %v", backm)
|
||||
return backm, nil
|
||||
case <-timeout:
|
||||
return nil, fmt.Errorf("timeout waiting for server %d response", serverId)
|
||||
}
|
||||
}
|
||||
|
||||
func SendMsgAll(m *msg.Msg) {
|
||||
data, err := GoUtil.GobMarshal(m)
|
||||
if err != nil {
|
||||
@ -138,7 +179,12 @@ func SendMsgAll(m *msg.Msg) {
|
||||
|
||||
func processMsg(a *Agent, m *msg.Msg) error {
|
||||
var err error
|
||||
if fun, ok := FuncMap[m.Type]; ok {
|
||||
|
||||
funcMapMu.RLock()
|
||||
fun, ok := FuncMap[m.Type]
|
||||
funcMapMu.RUnlock()
|
||||
|
||||
if ok {
|
||||
err = fun(a, m)
|
||||
} else {
|
||||
MsgChan <- m //交由game Module消息处理
|
||||
@ -147,7 +193,21 @@ func processMsg(a *Agent, m *msg.Msg) error {
|
||||
}
|
||||
|
||||
func registerFunc(key int, fun func(*Agent, *msg.Msg) error) {
|
||||
funcMapMu.Lock()
|
||||
FuncMap[key] = fun
|
||||
funcMapMu.Unlock()
|
||||
}
|
||||
|
||||
func registerChanel(key string, chanel chan *msg.Msg) {
|
||||
callbackChanMu.Lock()
|
||||
CallbackChan[key] = chanel
|
||||
callbackChanMu.Unlock()
|
||||
}
|
||||
|
||||
func unregisterChanel(key string) {
|
||||
callbackChanMu.Lock()
|
||||
delete(CallbackChan, key)
|
||||
callbackChanMu.Unlock()
|
||||
}
|
||||
|
||||
func sendGameMsg(m *msg.Msg) {
|
||||
@ -1,17 +1,8 @@
|
||||
package mergeCluster
|
||||
|
||||
import (
|
||||
"encoding/gob"
|
||||
"server/game/mod/msg"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gob.Register(&msg.Msg{})
|
||||
gob.Register(&ClusterJoinData{})
|
||||
}
|
||||
|
||||
type ClusterJoinData struct {
|
||||
ServerId int
|
||||
Country int
|
||||
RemoteAddr string
|
||||
}
|
||||
|
||||
@ -1,41 +0,0 @@
|
||||
package startOrderCfg
|
||||
|
||||
import (
|
||||
"server/gamedata"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type StartOrderCfg struct {
|
||||
}
|
||||
|
||||
var CFG_NAME = "StartOrder"
|
||||
|
||||
func init() {
|
||||
gamedata.InitCfg(CFG_NAME)
|
||||
}
|
||||
|
||||
// 根据step 获取初始订单
|
||||
func GetStartOrderByStep(id int) []*gamedata.StartOrderData {
|
||||
ret := make([]*gamedata.StartOrderData, 0)
|
||||
data, err := gamedata.GetData(CFG_NAME)
|
||||
if err != nil {
|
||||
return ret
|
||||
}
|
||||
for k, v := range data {
|
||||
record := v.(map[string]interface{})
|
||||
stepVal := gamedata.ParseInt(record["step"])
|
||||
var MergeList []int
|
||||
for _, vv := range record["merge_id_list"].([]interface{}) {
|
||||
MergeList = append(MergeList, gamedata.ParseInt(vv))
|
||||
}
|
||||
if int(stepVal) == id {
|
||||
OrderId, _ := strconv.Atoi(k)
|
||||
ret = append(ret, &gamedata.StartOrderData{
|
||||
Id: OrderId,
|
||||
Step: int(stepVal),
|
||||
MergeList: MergeList,
|
||||
})
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
@ -1,46 +0,0 @@
|
||||
package activityCfg
|
||||
|
||||
import (
|
||||
"server/GoUtil"
|
||||
"server/gamedata"
|
||||
"server/pkg/github.com/name5566/leaf/log"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const (
|
||||
CFG_ACTIVITY = "Activity"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gamedata.InitCfg(CFG_ACTIVITY)
|
||||
}
|
||||
|
||||
func GetActivityList() []*gamedata.ActivityData {
|
||||
data, err := gamedata.GetData(CFG_ACTIVITY)
|
||||
if err != nil {
|
||||
log.Debug("GetActivityList err:%v", err)
|
||||
}
|
||||
Now := GoUtil.Now()
|
||||
var List []*gamedata.ActivityData
|
||||
|
||||
for k, v := range data {
|
||||
StartTimeStr := gamedata.GetStringValue(v, "StartTime")
|
||||
EndTimeStr := gamedata.GetStringValue(v, "EndTime")
|
||||
StartTime := GoUtil.ParseTime(StartTimeStr)
|
||||
EndTime := GoUtil.ParseTime(EndTimeStr)
|
||||
if Now >= StartTime && Now <= EndTime {
|
||||
Id, _ := strconv.Atoi(k)
|
||||
Type := gamedata.GetIntValue(v, "Type")
|
||||
Name := gamedata.GetStringValue(v, "Name")
|
||||
Title := gamedata.GetStringValue(v, "Title")
|
||||
ActivityData := &gamedata.ActivityData{
|
||||
Id: Id,
|
||||
Type: Type,
|
||||
Name: Name,
|
||||
Title: Title,
|
||||
}
|
||||
List = append(List, ActivityData)
|
||||
}
|
||||
}
|
||||
return List
|
||||
}
|
||||
145
src/server/conf/activity/activity_cfg.go
Normal file
145
src/server/conf/activity/activity_cfg.go
Normal file
@ -0,0 +1,145 @@
|
||||
package activityCfg
|
||||
|
||||
import (
|
||||
"server/game/mod/item"
|
||||
GoUtil "server/game_util"
|
||||
"server/gamedata"
|
||||
"strconv"
|
||||
|
||||
"gitea.bywaystudios.com/pet_home/leaf/log"
|
||||
)
|
||||
|
||||
const (
|
||||
CFG_ACTIVITY = "Activity"
|
||||
CFG_ACTIVITY_GIFT = "ActivityGift"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gamedata.InitCfg(CFG_ACTIVITY)
|
||||
gamedata.InitCfg(CFG_ACTIVITY_GIFT)
|
||||
}
|
||||
|
||||
func GetActivityGiftId(chargeId int) int {
|
||||
data, err := gamedata.GetData(CFG_ACTIVITY_GIFT)
|
||||
if err != nil {
|
||||
log.Debug("GetActivityGiftId err:%v", err)
|
||||
return 0
|
||||
}
|
||||
for _, v := range data {
|
||||
ChargeId := gamedata.GetIntValue(v, "ChargeId")
|
||||
if ChargeId == chargeId {
|
||||
return gamedata.GetIntValue(v, "AId")
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func GetActivityGiftItems(chargeId int) []*item.Item {
|
||||
data, err := gamedata.GetData(CFG_ACTIVITY_GIFT)
|
||||
if err != nil {
|
||||
log.Debug("GetActivityGiftItems err:%v", err)
|
||||
return nil
|
||||
}
|
||||
for _, v := range data {
|
||||
ChargeId := gamedata.GetIntValue(v, "ChargeId")
|
||||
if ChargeId == chargeId {
|
||||
Items := gamedata.GetItemList(v, "Items")
|
||||
return Items
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetActivityList() []*gamedata.ActivityData {
|
||||
data, err := gamedata.GetData(CFG_ACTIVITY)
|
||||
if err != nil {
|
||||
log.Debug("GetActivityList err:%v", err)
|
||||
return nil
|
||||
}
|
||||
List := make([]*gamedata.ActivityData, 0, len(data))
|
||||
|
||||
for k, v := range data {
|
||||
StartTimeStr := gamedata.GetStringValue(v, "StartTime")
|
||||
EndTimeStr := gamedata.GetStringValue(v, "EndTime")
|
||||
StartTime := GoUtil.ParseTime(StartTimeStr)
|
||||
EndTime := GoUtil.ParseTime(EndTimeStr)
|
||||
Type := gamedata.GetIntValue(v, "Type")
|
||||
Name := gamedata.GetStringValue(v, "Name")
|
||||
Title := gamedata.GetStringValue(v, "Title")
|
||||
Level := gamedata.GetIntValue(v, "Level")
|
||||
ActivityData := &gamedata.ActivityData{
|
||||
Id: GoUtil.Int(k),
|
||||
Type: Type,
|
||||
AType: gamedata.GetIntValue(v, "AType"),
|
||||
Name: Name,
|
||||
Title: Title,
|
||||
Level: Level,
|
||||
StartTime: StartTime,
|
||||
EndTime: EndTime,
|
||||
}
|
||||
List = append(List, ActivityData)
|
||||
}
|
||||
return List
|
||||
}
|
||||
func GetActivityListOrigin() []*gamedata.ActivityData {
|
||||
data, err := gamedata.GetData(CFG_ACTIVITY)
|
||||
if err != nil {
|
||||
log.Debug("GetActivityList err:%v", err)
|
||||
return nil
|
||||
}
|
||||
List := make([]*gamedata.ActivityData, 0, len(data))
|
||||
|
||||
for k, v := range data {
|
||||
StartTimeStr := gamedata.GetStringValue(v, "StartTime")
|
||||
EndTimeStr := gamedata.GetStringValue(v, "EndTime")
|
||||
StartTime := GoUtil.ParseTime(StartTimeStr)
|
||||
EndTime := GoUtil.ParseTime(EndTimeStr)
|
||||
Id, err := strconv.Atoi(k)
|
||||
if err != nil {
|
||||
log.Debug("GetActivityList parse id err:%v, key:%s", err, k)
|
||||
continue
|
||||
}
|
||||
Type := gamedata.GetIntValue(v, "Type")
|
||||
Name := gamedata.GetStringValue(v, "Name")
|
||||
Title := gamedata.GetStringValue(v, "Title")
|
||||
Level := gamedata.GetIntValue(v, "Level")
|
||||
ActivityData := &gamedata.ActivityData{
|
||||
Id: Id,
|
||||
Type: Type,
|
||||
AType: gamedata.GetIntValue(v, "AType"),
|
||||
Name: Name,
|
||||
Title: Title,
|
||||
Level: Level,
|
||||
StartTime: StartTime,
|
||||
EndTime: EndTime,
|
||||
}
|
||||
List = append(List, ActivityData)
|
||||
}
|
||||
return List
|
||||
}
|
||||
|
||||
func GetActivityRewardItems(ActId int) []*item.Item {
|
||||
data, err := gamedata.GetData(CFG_ACTIVITY_GIFT)
|
||||
if err != nil {
|
||||
log.Debug("GetActivityRewardItems err:%v", err)
|
||||
return nil
|
||||
}
|
||||
for _, v := range data {
|
||||
ChargeId := gamedata.GetIntValue(v, "ChargeId")
|
||||
AId := gamedata.GetIntValue(v, "AId")
|
||||
if ChargeId == 0 && AId == ActId {
|
||||
Items := gamedata.GetItemList(v, "Items")
|
||||
return Items
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetActivityRecycleMail(ActId int) (string, string, string) {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_ACTIVITY, ActId)
|
||||
if err != nil {
|
||||
log.Debug("GetActivityRecycleMail err:%v", err)
|
||||
return "", "", ""
|
||||
}
|
||||
return gamedata.GetStringValue(data, "Title"), gamedata.GetStringValue(data, "Mail_Title"), gamedata.GetStringValue(data, "Mail_Content")
|
||||
}
|
||||
@ -1,9 +1,11 @@
|
||||
package avatarCfg
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"server/gamedata"
|
||||
"server/pkg/github.com/name5566/leaf/log"
|
||||
"strconv"
|
||||
|
||||
"gitea.bywaystudios.com/pet_home/leaf/log"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -20,7 +22,7 @@ func GetInitList() []int {
|
||||
log.Debug("GetInitList err: %v", err)
|
||||
return nil
|
||||
}
|
||||
r := make([]int, 0)
|
||||
r := make([]int, 0, len(data))
|
||||
for k, v := range data {
|
||||
IsInit := gamedata.GetIntValue(v, "Init")
|
||||
if IsInit == 1 {
|
||||
@ -31,6 +33,15 @@ func GetInitList() []int {
|
||||
return r
|
||||
}
|
||||
|
||||
func GetRandInitId() int {
|
||||
list := GetInitList()
|
||||
if len(list) == 0 {
|
||||
return 0
|
||||
}
|
||||
index := rand.Intn(len(list))
|
||||
return list[index]
|
||||
}
|
||||
|
||||
func CheckExist(Id int) bool {
|
||||
data, err := gamedata.GetData(CFG_AVATAR)
|
||||
if err != nil {
|
||||
@ -40,3 +51,17 @@ func CheckExist(Id int) bool {
|
||||
_, ok := data[strconv.Itoa(Id)]
|
||||
return ok
|
||||
}
|
||||
|
||||
func GetAllId() []int {
|
||||
data, err := gamedata.GetData(CFG_AVATAR)
|
||||
if err != nil {
|
||||
log.Debug("GetAllId err: %v", err)
|
||||
return nil
|
||||
}
|
||||
r := make([]int, 0, len(data))
|
||||
for k := range data {
|
||||
Id, _ := strconv.Atoi(k)
|
||||
r = append(r, Id)
|
||||
}
|
||||
return r
|
||||
}
|
||||
@ -1,39 +0,0 @@
|
||||
package baseCfg
|
||||
|
||||
import (
|
||||
"server/gamedata"
|
||||
"server/pkg/github.com/name5566/leaf/log"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const (
|
||||
CFG_BASE = "Base"
|
||||
)
|
||||
|
||||
const (
|
||||
ENERGY_SHOP_MUL = "energy_shop_mul"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gamedata.InitCfg(CFG_BASE)
|
||||
}
|
||||
|
||||
func GetEnergyByMul(T int) float64 {
|
||||
data, err := gamedata.GetDataByKey(CFG_BASE, ENERGY_SHOP_MUL)
|
||||
if err != nil {
|
||||
log.Debug("GetEnergyByMul err:%v", err)
|
||||
return 0
|
||||
}
|
||||
d := data["Value"].(map[string]interface{})
|
||||
if len(d) == 0 {
|
||||
return 0
|
||||
}
|
||||
T = min(T, len(d))
|
||||
T1 := strconv.Itoa(T)
|
||||
if v, ok := d[T1]; ok {
|
||||
return v.(float64)
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
|
||||
}
|
||||
98
src/server/conf/base/base_cfg.go
Normal file
98
src/server/conf/base/base_cfg.go
Normal file
@ -0,0 +1,98 @@
|
||||
package baseCfg
|
||||
|
||||
import (
|
||||
"server/game/mod/item"
|
||||
"server/gamedata"
|
||||
"strconv"
|
||||
|
||||
"gitea.bywaystudios.com/pet_home/leaf/log"
|
||||
)
|
||||
|
||||
const (
|
||||
CFG_BASE = "Base"
|
||||
)
|
||||
|
||||
const (
|
||||
ENERGY_SHOP_MUL = "energy_shop_mul"
|
||||
ENERGY_CFG = "BaseEnergy"
|
||||
MAX_ENERGY_LEVEL = 999 // 最大能量等级上限
|
||||
)
|
||||
|
||||
func init() {
|
||||
gamedata.InitCfg(CFG_BASE)
|
||||
gamedata.InitCfg(ENERGY_CFG)
|
||||
}
|
||||
|
||||
func GetEnergyByMul(T int) float64 {
|
||||
data, err := gamedata.GetDataByKey(CFG_BASE, ENERGY_SHOP_MUL)
|
||||
if err != nil {
|
||||
log.Debug("GetEnergyByMul err:%v", err)
|
||||
return 0
|
||||
}
|
||||
|
||||
valueData, ok := data["Value"]
|
||||
if !ok {
|
||||
log.Debug("GetEnergyByMul: Value field not found")
|
||||
return 0
|
||||
}
|
||||
|
||||
d, ok := valueData.(map[string]interface{})
|
||||
if !ok || len(d) == 0 {
|
||||
log.Debug("GetEnergyByMul: Value is not a valid map")
|
||||
return 0
|
||||
}
|
||||
|
||||
T = min(T, len(d))
|
||||
T1 := strconv.Itoa(T)
|
||||
if v, ok := d[T1]; ok {
|
||||
if floatVal, ok := v.(float64); ok {
|
||||
return floatVal
|
||||
}
|
||||
log.Debug("GetEnergyByMul: value is not float64, key=%s", T1)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func GetFriendReplyReward() []*item.Item {
|
||||
data, err := gamedata.GetDataByKey(CFG_BASE, "friend_reply")
|
||||
if err != nil {
|
||||
log.Debug("GetFriendReplyReward err:%v", err)
|
||||
return nil
|
||||
}
|
||||
return gamedata.GetItemList(data, "Value")
|
||||
}
|
||||
|
||||
func GetEnergyByADNum() []*item.Item {
|
||||
data, err := gamedata.GetDataByKey(CFG_BASE, "ad_energy_gift")
|
||||
if err != nil {
|
||||
log.Debug("GetEnergyByADNum err:%v", err)
|
||||
return nil
|
||||
}
|
||||
return gamedata.GetItemList(data, "Value")
|
||||
}
|
||||
|
||||
func GetMaxEnergyMul(Lv int, Energy int) int {
|
||||
Mul := 0
|
||||
for i := 1; i <= MAX_ENERGY_LEVEL; i++ {
|
||||
data, err := gamedata.GetDataByIntKey(ENERGY_CFG, i)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
UnlockLv := gamedata.GetIntValue(data, "UnlockLv")
|
||||
needEnergy := gamedata.GetIntValue(data, "NeedEnergy")
|
||||
if Lv < UnlockLv || Energy < needEnergy {
|
||||
break
|
||||
}
|
||||
Mul = i - 1
|
||||
}
|
||||
return Mul
|
||||
}
|
||||
|
||||
func GetLimitEnergyMul(Lv int) int {
|
||||
data, err := gamedata.GetDataByIntKey(ENERGY_CFG, Lv+1)
|
||||
if err != nil {
|
||||
log.Debug("GetLimitEnergyMul err:%v, Lv=%d", err, Lv)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Limit")
|
||||
}
|
||||
@ -1,12 +1,13 @@
|
||||
package cardCfg
|
||||
|
||||
import (
|
||||
"server/GoUtil"
|
||||
"server/game/mod/item"
|
||||
GoUtil "server/game_util"
|
||||
"server/gamedata"
|
||||
"server/pkg/github.com/name5566/leaf/log"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"gitea.bywaystudios.com/pet_home/leaf/log"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -28,51 +29,73 @@ func init() {
|
||||
func GetAllCollectReward() []*item.Item {
|
||||
data, err := gamedata.GetDataByKey(CARD_CONST_CFG_NAME, "all_collect_reward")
|
||||
if err != nil {
|
||||
log.Debug("GetAllCollectReward data not found")
|
||||
log.Debug("GetAllCollectReward err:%v", err)
|
||||
return nil
|
||||
}
|
||||
return item.ParseItem(data["Value"])
|
||||
if value, ok := data["Value"]; ok {
|
||||
return item.ParseItem(value)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func GetStarById(Id int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CARD_DETAIL_CFG_NAME, Id)
|
||||
if err != nil {
|
||||
log.Debug("GetStarById data not found")
|
||||
log.Debug("GetStarById err:%v, Id=%d", err, Id)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Star")
|
||||
}
|
||||
|
||||
func GetRoundById(Id int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CARD_DETAIL_CFG_NAME, Id)
|
||||
if err != nil {
|
||||
log.Debug("GetRoundById err:%v, Id=%d", err, Id)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Round")
|
||||
}
|
||||
|
||||
// 获取开启卡包获得的卡牌数量
|
||||
func GetPackRewardCnt(Star int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CARD_PACK_CFG_NAME, Star)
|
||||
|
||||
if err != nil {
|
||||
log.Debug("GetPackRewardCnt data not found")
|
||||
log.Debug("GetPackRewardCnt err:%v, Star=%d", err, Star)
|
||||
return 0
|
||||
}
|
||||
|
||||
return gamedata.GetIntValue(data, "RewardCnt")
|
||||
}
|
||||
|
||||
// 获取开启开包比得x星卡
|
||||
// 获取开启开包必得x星卡
|
||||
func GetPackMustHave(Star int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CARD_PACK_CFG_NAME, Star)
|
||||
if err != nil {
|
||||
log.Debug("GetPackMustHave data not found")
|
||||
log.Debug("GetPackMustHave err:%v, Star=%d", err, Star)
|
||||
return 0
|
||||
}
|
||||
|
||||
return gamedata.GetIntValue(data, "MustHave")
|
||||
}
|
||||
|
||||
// 根据星级获取卡牌列表
|
||||
func GetCardListByStar(Star, IsGold int) []int {
|
||||
var CardList []int
|
||||
func GetCardListByStar(Round, Star, IsGold int) []int {
|
||||
data, err := gamedata.GetData(CARD_DETAIL_CFG_NAME)
|
||||
if err != nil {
|
||||
log.Debug("GetCardListByStar data not found")
|
||||
log.Debug("GetCardListByStar err:%v", err)
|
||||
return nil
|
||||
}
|
||||
CardList := make([]int, 0, len(data)/10)
|
||||
for k, v := range data {
|
||||
Extra := gamedata.GetIntValue(v, "Round")
|
||||
if Round < Extra {
|
||||
continue
|
||||
}
|
||||
vStar := gamedata.GetIntValue(v, "Star")
|
||||
isGold := gamedata.GetIntValue(v, "IsGold")
|
||||
if vStar == Star && IsGold == isGold {
|
||||
id, _ := strconv.Atoi(k)
|
||||
id, err := strconv.Atoi(k)
|
||||
if err != nil {
|
||||
log.Debug("GetCardListByStar parse id err:%v, key=%s", err, k)
|
||||
continue
|
||||
}
|
||||
CardList = append(CardList, id)
|
||||
}
|
||||
}
|
||||
@ -80,16 +103,20 @@ func GetCardListByStar(Star, IsGold int) []int {
|
||||
}
|
||||
|
||||
// 获取随机卡牌
|
||||
func GetRandListByStar(Star int) []int {
|
||||
var randList []int
|
||||
func GetRandListByStar(Star int) map[int]int {
|
||||
data, err := gamedata.GetDataByIntKey(CARD_PACK_CFG_NAME, Star)
|
||||
if err != nil {
|
||||
log.Debug("GetRandListByStar data not found")
|
||||
log.Debug("GetRandListByStar err:%v, Star=%d", err, Star)
|
||||
return nil
|
||||
}
|
||||
r1 := gamedata.GetStringValue(data, "RandRate")
|
||||
r2 := strings.Split(r1, ",")
|
||||
randList = GoUtil.SliceStringToInt(r2)
|
||||
return randList
|
||||
randList := GoUtil.SliceStringToInt(r2)
|
||||
r := make(map[int]int, len(randList))
|
||||
for k, v := range randList {
|
||||
r[k+1] = v
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// 获取卡牌收集奖励
|
||||
@ -106,33 +133,33 @@ func GetCollectReward(Color int) ([]*item.Item, int) {
|
||||
}
|
||||
|
||||
// 获取兑换奖励
|
||||
func GetExchangeCfg(Id int) (int, []*item.Item, []int) {
|
||||
func GetExchangeCfg(Id int) (int, []*item.Item) {
|
||||
data, err := gamedata.GetDataByIntKey(CARD_EXCHANGE_CFG, Id)
|
||||
if err != nil {
|
||||
log.Debug("GetExchangeCfg data not found")
|
||||
return 0, nil, nil
|
||||
log.Debug("GetExchangeCfg err:%v, Id=%d", err, Id)
|
||||
return 0, nil
|
||||
}
|
||||
itemNum := gamedata.GetIntValue(data, "Item")
|
||||
itemList := []*item.Item{item.NewItem(item.ITEM_ENERGY_ID, itemNum)}
|
||||
CostStar := gamedata.GetIntValue(data, "CostStar")
|
||||
CardPackStr := gamedata.GetStringValue(data, "CardPack")
|
||||
s1 := CardPackStr[1 : len(CardPackStr)-1]
|
||||
CardPack := GoUtil.SliceStringToInt(strings.Split(s1, ","))
|
||||
return CostStar, itemList, CardPack
|
||||
itemList := gamedata.GetItemList(data, "Item")
|
||||
return CostStar, itemList
|
||||
}
|
||||
|
||||
// 根据系列获取卡牌列表
|
||||
func GetCardListByColor(Id int) []int {
|
||||
data, err := gamedata.GetData(CARD_DETAIL_CFG_NAME)
|
||||
if err != nil {
|
||||
log.Debug("GetCardListByColor data not found")
|
||||
return []int{}
|
||||
log.Debug("GetCardListByColor err:%v, Id=%d", err, Id)
|
||||
return nil
|
||||
}
|
||||
var r []int
|
||||
r := make([]int, 0, len(data)/5)
|
||||
for k, v := range data {
|
||||
color := gamedata.GetIntValue(v, "PictureAlbum")
|
||||
if color == Id {
|
||||
k1, _ := strconv.Atoi(k)
|
||||
k1, err := strconv.Atoi(k)
|
||||
if err != nil {
|
||||
log.Debug("GetCardListByColor parse id err:%v, key=%s", err, k)
|
||||
continue
|
||||
}
|
||||
r = append(r, k1)
|
||||
}
|
||||
}
|
||||
@ -140,24 +167,42 @@ func GetCardListByColor(Id int) []int {
|
||||
}
|
||||
|
||||
// 获取所有卡牌id
|
||||
func GetAllCardId() []int {
|
||||
func GetAllCardId(Round int) []int {
|
||||
data, err := gamedata.GetData(CARD_DETAIL_CFG_NAME)
|
||||
if err != nil {
|
||||
log.Debug("GetCardListByColor data not found")
|
||||
return []int{}
|
||||
log.Debug("GetAllCardId err:%v, Round=%d", err, Round)
|
||||
return nil
|
||||
}
|
||||
var r []int
|
||||
for k := range data {
|
||||
k1, _ := strconv.Atoi(k)
|
||||
r := make([]int, 0, len(data))
|
||||
for k, v := range data {
|
||||
Extra := gamedata.GetIntValue(v, "Round")
|
||||
if Round < Extra {
|
||||
continue
|
||||
}
|
||||
k1, err := strconv.Atoi(k)
|
||||
if err != nil {
|
||||
log.Debug("GetAllCardId parse id err:%v, key=%s", err, k)
|
||||
continue
|
||||
}
|
||||
r = append(r, k1)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func CheckCardIsGold(Id int) bool {
|
||||
data, err := gamedata.GetDataByIntKey(CARD_DETAIL_CFG_NAME, Id)
|
||||
if err != nil {
|
||||
log.Debug("CheckCardIsGold err:%v, Id=%d", err, Id)
|
||||
return false
|
||||
}
|
||||
return gamedata.GetIntValue(data, "IsGold") == 1
|
||||
}
|
||||
|
||||
func GetCardDuration() int64 {
|
||||
data, err := gamedata.GetDataByKey(CARD_CONST_CFG_NAME, "duration")
|
||||
if err != nil {
|
||||
log.Debug("GetCardDuration data not found")
|
||||
log.Debug("GetCardDuration err:%v", err)
|
||||
return 0
|
||||
}
|
||||
return int64(gamedata.GetIntValue(data, "Value"))
|
||||
}
|
||||
@ -165,7 +210,8 @@ func GetCardDuration() int64 {
|
||||
func GetExTimes() int {
|
||||
data, err := gamedata.GetDataByKey(CARD_CONST_CFG_NAME, "exchange_times")
|
||||
if err != nil {
|
||||
log.Debug("GetExTimes data not found")
|
||||
log.Debug("GetExTimes err:%v", err)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
@ -173,7 +219,29 @@ func GetExTimes() int {
|
||||
func GetReqTimes() int {
|
||||
data, err := gamedata.GetDataByKey(CARD_CONST_CFG_NAME, "request_times")
|
||||
if err != nil {
|
||||
log.Debug("GetReqTimes data not found")
|
||||
log.Debug("GetReqTimes err:%v", err)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
func GetItemIdByCardId(CardId int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CARD_DETAIL_CFG_NAME, CardId)
|
||||
if err != nil {
|
||||
log.Debug("GetItemIdByCardId err:%v, CardId=%d", err, CardId)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "ItemId")
|
||||
}
|
||||
|
||||
func GetSeasonFirstReward() []*item.Item {
|
||||
data, err := gamedata.GetDataByKey(CARD_CONST_CFG_NAME, "season_first")
|
||||
if err != nil {
|
||||
log.Debug("GetSeasonFirstReward err:%v", err)
|
||||
return nil
|
||||
}
|
||||
if value, ok := data["Value"]; ok {
|
||||
return item.ParseItem(value)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
156
src/server/conf/catnip/catnip_cfg.go
Normal file
156
src/server/conf/catnip/catnip_cfg.go
Normal file
@ -0,0 +1,156 @@
|
||||
package catnipCfg
|
||||
|
||||
import (
|
||||
"server/game/mod/item"
|
||||
GoUtil "server/game_util"
|
||||
"server/gamedata"
|
||||
|
||||
"gitea.bywaystudios.com/pet_home/leaf/log"
|
||||
)
|
||||
|
||||
const (
|
||||
CATNIP_TEMPLATE_CFG_NAME = "CatnipTemplate"
|
||||
CATNIP_JACKPOT_CFG_NAME = "CatnipJackpot"
|
||||
CATNIP_MULTIPLIER_CFG_NAME = "CatnipMultiplier"
|
||||
CATNIP_GAME_CFG_NAME = "CatnipGame"
|
||||
)
|
||||
|
||||
const (
|
||||
CATNIP_REWARD_TYPE_LOW = 1
|
||||
CATNIP_REWARD_TYPE_MID = 2
|
||||
CATNIP_REWARD_TYPE_HIGH = 3
|
||||
)
|
||||
|
||||
func init() {
|
||||
gamedata.InitCfg(CATNIP_TEMPLATE_CFG_NAME)
|
||||
gamedata.InitCfg(CATNIP_JACKPOT_CFG_NAME)
|
||||
gamedata.InitCfg(CATNIP_MULTIPLIER_CFG_NAME)
|
||||
gamedata.InitCfg(CATNIP_GAME_CFG_NAME)
|
||||
}
|
||||
|
||||
func GetGameNum(Id int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CATNIP_TEMPLATE_CFG_NAME, Id)
|
||||
if err != nil {
|
||||
log.Debug("GetGameNum err:%v, Id=%d", err, Id)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "PassNum")
|
||||
}
|
||||
|
||||
func GetGameMaxProgress(Id int) int {
|
||||
TemplateId := GetTemplateId(Id)
|
||||
data, err := gamedata.GetData(CATNIP_GAME_CFG_NAME)
|
||||
if err != nil {
|
||||
log.Debug("GetGameMaxProgress err:%v, Id=%d", err, Id)
|
||||
return 0
|
||||
}
|
||||
MaxProgress := 0
|
||||
for _, v := range data {
|
||||
if gamedata.GetIntValue(v, "Template") != TemplateId {
|
||||
continue
|
||||
}
|
||||
MaxProgress = max(MaxProgress, gamedata.GetIntValue(v, "Need"))
|
||||
}
|
||||
return MaxProgress
|
||||
}
|
||||
|
||||
func GetJackpotItem(Mul int) (int, []*item.Item, int, int) {
|
||||
data, err := gamedata.GetData(CATNIP_JACKPOT_CFG_NAME)
|
||||
if err != nil {
|
||||
log.Debug("GetJackpotItem err:%v, Mul=%d", err, Mul)
|
||||
return 0, nil, 0, 0
|
||||
}
|
||||
JackpotType := GetJackpotType(Mul)
|
||||
r := make(map[int]int, len(data))
|
||||
for k, v := range data {
|
||||
if gamedata.GetIntValue(v, "Type") == JackpotType {
|
||||
r[GoUtil.Int(k)] = 1
|
||||
}
|
||||
}
|
||||
Id := GoUtil.RandMap(r)
|
||||
if Id == 0 {
|
||||
return 0, nil, 0, 0
|
||||
}
|
||||
itemData, err := gamedata.GetDataByIntKey(CATNIP_JACKPOT_CFG_NAME, Id)
|
||||
if err != nil {
|
||||
log.Debug("GetJackpotItem get itemData err:%v, Id=%d", err, Id)
|
||||
return 0, nil, 0, 0
|
||||
}
|
||||
return Id, gamedata.GetItemList(itemData, "Items"), gamedata.GetIntValue(itemData, "Growth"), gamedata.GetIntValue(itemData, "FriendItems")
|
||||
}
|
||||
|
||||
func GetJackpotType(Mul int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CATNIP_MULTIPLIER_CFG_NAME, Mul)
|
||||
if err != nil {
|
||||
log.Debug("GetJackpotType err:%v, Mul=%d", err, Mul)
|
||||
return 0
|
||||
}
|
||||
R := map[int]int{
|
||||
CATNIP_REWARD_TYPE_LOW: gamedata.GetIntValue(data, "Low"),
|
||||
CATNIP_REWARD_TYPE_MID: gamedata.GetIntValue(data, "Mid"),
|
||||
CATNIP_REWARD_TYPE_HIGH: gamedata.GetIntValue(data, "High"),
|
||||
}
|
||||
return GoUtil.RandMap(R)
|
||||
}
|
||||
|
||||
func GetTemplateId(Id int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CATNIP_TEMPLATE_CFG_NAME, Id)
|
||||
if err != nil {
|
||||
log.Debug("GetTemplateId err:%v, Id=%d", err, Id)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Template")
|
||||
}
|
||||
|
||||
func GetProgressReward(Id int, Rewards []int, Progress int) ([]*item.Item, []int) {
|
||||
TemplateId := GetTemplateId(Id)
|
||||
data, err := gamedata.GetData(CATNIP_GAME_CFG_NAME)
|
||||
if err != nil {
|
||||
log.Debug("GetProgressReward err:%v, Id=%d", err, Id)
|
||||
return nil, nil
|
||||
}
|
||||
Items := make([]*item.Item, 0, len(data))
|
||||
Ids := make([]int, 0, len(data))
|
||||
for k, v := range data {
|
||||
rewardId := GoUtil.Int(k)
|
||||
if !GoUtil.InArray(rewardId, Rewards) && gamedata.GetIntValue(v, "Need") < Progress && gamedata.GetIntValue(v, "Template") == TemplateId {
|
||||
Items = append(Items, gamedata.GetItemList(v, "Items")...)
|
||||
Ids = append(Ids, rewardId)
|
||||
}
|
||||
}
|
||||
return Items, Ids
|
||||
}
|
||||
|
||||
func GetProgressNum(Id int) int {
|
||||
TemplateId := GetTemplateId(Id)
|
||||
data, err := gamedata.GetData(CATNIP_GAME_CFG_NAME)
|
||||
if err != nil {
|
||||
log.Debug("GetProgressNum err:%v, Id=%d", err, Id)
|
||||
return 0
|
||||
}
|
||||
Num := 0
|
||||
for _, v := range data {
|
||||
if gamedata.GetIntValue(v, "Template") == TemplateId {
|
||||
Num++
|
||||
}
|
||||
}
|
||||
return Num
|
||||
}
|
||||
|
||||
func GetItemCost(Id, Mul int) []*item.Item {
|
||||
data, err := gamedata.GetDataByIntKey(CATNIP_TEMPLATE_CFG_NAME, Id)
|
||||
if err != nil {
|
||||
log.Debug("GetItemCost err:%v, Id=%d", err, Id)
|
||||
return nil
|
||||
}
|
||||
return item.MutilItem(gamedata.GetItemList(data, "ItemCost"), Mul)
|
||||
}
|
||||
|
||||
func GetGrandReward(Id int) []*item.Item {
|
||||
data, err := gamedata.GetDataByIntKey(CATNIP_TEMPLATE_CFG_NAME, Id)
|
||||
if err != nil {
|
||||
log.Debug("GetGrandReward err:%v, Id=%d", err, Id)
|
||||
return nil
|
||||
}
|
||||
return gamedata.GetItemList(data, "Reward")
|
||||
}
|
||||
@ -1,47 +0,0 @@
|
||||
package champshipCfg
|
||||
|
||||
import (
|
||||
"server/GoUtil"
|
||||
"server/game/mod/item"
|
||||
"server/gamedata"
|
||||
)
|
||||
|
||||
const (
|
||||
CFG_CHAMPSHIP_SCORE = "ChampshipScore"
|
||||
CFG_CHAMPSHIP_RANK = "ChampshipRank"
|
||||
CFG_CHAMPSHIP_JACKPOT = "ChampshipJackpot"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gamedata.InitCfg(CFG_CHAMPSHIP_SCORE)
|
||||
gamedata.InitCfg(CFG_CHAMPSHIP_RANK)
|
||||
gamedata.InitCfg(CFG_CHAMPSHIP_JACKPOT)
|
||||
}
|
||||
|
||||
func GetChessScore(ChessLv int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_CHAMPSHIP_SCORE, ChessLv)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Score")
|
||||
}
|
||||
|
||||
func GetReward(Reward, Score int) (int, []*item.Item) {
|
||||
data, err := gamedata.GetData(CFG_CHAMPSHIP_JACKPOT)
|
||||
if err != nil {
|
||||
return Reward, nil
|
||||
}
|
||||
r := make([]*item.Item, 0)
|
||||
for k, v := range data {
|
||||
Id := GoUtil.Int(k)
|
||||
if Reward >= Id {
|
||||
continue
|
||||
}
|
||||
Reward = max(Reward, Id)
|
||||
if Score >= gamedata.GetIntValue(v, "Score") {
|
||||
Items := item.ParseItem(gamedata.GetStringValue(v, "Items"))
|
||||
r = item.Merge(r, Items)
|
||||
}
|
||||
}
|
||||
return Reward, r
|
||||
}
|
||||
148
src/server/conf/champship/champship_cfg.go
Normal file
148
src/server/conf/champship/champship_cfg.go
Normal file
@ -0,0 +1,148 @@
|
||||
package champshipCfg
|
||||
|
||||
import (
|
||||
"server/game/mod/item"
|
||||
GoUtil "server/game_util"
|
||||
"server/gamedata"
|
||||
"strings"
|
||||
|
||||
"gitea.bywaystudios.com/pet_home/leaf/log"
|
||||
)
|
||||
|
||||
const (
|
||||
CFG_CHAMPSHIP_SCORE = "ChampshipScore"
|
||||
CFG_CHAMPSHIP_RANK = "ChampshipRank"
|
||||
CFG_CHAMPSHIP_JACKPOT = "ChampshipJackpot"
|
||||
CFG_CHAMPSHIP_GROUP = "ChampshipGroup"
|
||||
CFG_CHAMPSHIP_CONST = "ChampshipConst"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gamedata.InitCfg(CFG_CHAMPSHIP_SCORE)
|
||||
gamedata.InitCfg(CFG_CHAMPSHIP_RANK)
|
||||
gamedata.InitCfg(CFG_CHAMPSHIP_JACKPOT)
|
||||
gamedata.InitCfg(CFG_CHAMPSHIP_GROUP)
|
||||
gamedata.InitCfg(CFG_CHAMPSHIP_CONST)
|
||||
}
|
||||
|
||||
func GetGroupId(N int) int {
|
||||
data, err := gamedata.GetData(CFG_CHAMPSHIP_GROUP)
|
||||
if err != nil {
|
||||
log.Debug("GetGroupId err:%v, N=%d", err, N)
|
||||
return 1
|
||||
}
|
||||
for k, v := range data {
|
||||
if N >= gamedata.GetIntValue(v, "Min") && N <= gamedata.GetIntValue(v, "Max") {
|
||||
return GoUtil.Int(k)
|
||||
}
|
||||
}
|
||||
return 11
|
||||
}
|
||||
|
||||
func GetChessScore(ChessLv int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_CHAMPSHIP_SCORE, ChessLv)
|
||||
if err != nil {
|
||||
log.Debug("GetChessScore err:%v, ChessLv=%d", err, ChessLv)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Score")
|
||||
}
|
||||
|
||||
func GetReward(Reward, Score, activityId, orderFactor int) (int, []*item.Item) {
|
||||
data, err := gamedata.GetData(CFG_CHAMPSHIP_JACKPOT)
|
||||
if err != nil {
|
||||
log.Debug("GetReward err:%v, Reward=%d, Score=%d", err, Reward, Score)
|
||||
return Reward, nil
|
||||
}
|
||||
r := make([]*item.Item, 0, len(data))
|
||||
NewReward := Reward
|
||||
for _, v := range data {
|
||||
rewardGroupType := gamedata.GetIntValue(v, "RewardGroupType")
|
||||
if rewardGroupType != activityId {
|
||||
continue
|
||||
}
|
||||
Id := gamedata.GetIntValue(v, "Step")
|
||||
if Reward >= Id {
|
||||
continue
|
||||
}
|
||||
if Score < gamedata.GetIntValue(v, "Total") {
|
||||
continue
|
||||
}
|
||||
Items := item.ParseItem(gamedata.GetValue(v, "Items"))
|
||||
r = item.Merge(r, Items)
|
||||
NewReward = max(NewReward, Id)
|
||||
starReward := gamedata.GetIntValue(v, "StarReward")
|
||||
if starReward > 0 {
|
||||
starnum := int((float64(starReward) * float64(orderFactor) / 500)) * 5
|
||||
if starnum > 0 {
|
||||
r = append(r, item.NewItem(item.ITEM_STAR_ID, starnum))
|
||||
}
|
||||
}
|
||||
}
|
||||
return NewReward, r
|
||||
}
|
||||
|
||||
func GetRewardItems(Reward int) ([]*item.Item, int) {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_CHAMPSHIP_JACKPOT, Reward)
|
||||
if err != nil {
|
||||
log.Debug("GetRewardItems err:%v, Reward=%d", err, Reward)
|
||||
return nil, 0
|
||||
}
|
||||
return gamedata.GetItemList(data, "Items"), gamedata.GetIntValue(data, "Score")
|
||||
}
|
||||
|
||||
func GetRewardTotalScore(Reward int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_CHAMPSHIP_JACKPOT, Reward)
|
||||
if err != nil {
|
||||
log.Debug("GetRewardTotalScore err:%v, Reward=%d", err, Reward)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Total")
|
||||
}
|
||||
|
||||
func GetRankReward(Rank, yesterdayActivityId int) []*item.Item {
|
||||
data, err := gamedata.GetData(CFG_CHAMPSHIP_RANK)
|
||||
if err != nil {
|
||||
log.Debug("GetRankReward err:%v, Rank=%d, yesterdayActivityId=%d", err, Rank, yesterdayActivityId)
|
||||
return nil
|
||||
}
|
||||
for _, v := range data {
|
||||
if Rank >= gamedata.GetIntValue(v, "Min") && Rank <= gamedata.GetIntValue(v, "Max") && yesterdayActivityId == gamedata.GetIntValue(v, "RewardGroupType") {
|
||||
return gamedata.GetItemList(v, "Items")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetMaxRewardId() int {
|
||||
data, err := gamedata.GetData(CFG_CHAMPSHIP_JACKPOT)
|
||||
if err != nil {
|
||||
log.Debug("GetMaxRewardId err:%v", err)
|
||||
return 0
|
||||
}
|
||||
MaxId := 0
|
||||
for k := range data {
|
||||
Id := GoUtil.Int(k)
|
||||
if Id > MaxId {
|
||||
MaxId = Id
|
||||
}
|
||||
}
|
||||
return MaxId
|
||||
}
|
||||
|
||||
func GetChampshipActivityId() []int {
|
||||
data, err := gamedata.GetDataByKey(CFG_CHAMPSHIP_CONST, "RewardGroupType_const")
|
||||
if err != nil {
|
||||
log.Debug("GetChampshipActivityId err:%v", err)
|
||||
return nil
|
||||
}
|
||||
value := gamedata.GetStringValue(data, "Value")
|
||||
var res []int
|
||||
for _, v := range strings.Split(value, "|") {
|
||||
id := GoUtil.Int(v)
|
||||
if id > 0 {
|
||||
res = append(res, id)
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
@ -1,253 +0,0 @@
|
||||
package chargeCfg
|
||||
|
||||
import (
|
||||
"server/GoUtil"
|
||||
"server/game/mod/item"
|
||||
"server/gamedata"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
CFG_CHARGE = "Charge"
|
||||
CFG_DIAMOND_SHOP = "DiamondShop"
|
||||
CFG_ENERGY_SHOP = "EnergyShop"
|
||||
CFG_SEPCIAL_SHOP = "SpecialShop"
|
||||
CFG_FREE_SHOP = "FreeShop"
|
||||
CFG_CHARGE_CONST = "ChargeConst"
|
||||
CFG_CHARGE_GIFT = "ChargeGift"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gamedata.InitCfg(CFG_CHARGE)
|
||||
gamedata.InitCfg(CFG_DIAMOND_SHOP)
|
||||
gamedata.InitCfg(CFG_ENERGY_SHOP)
|
||||
gamedata.InitCfg(CFG_SEPCIAL_SHOP)
|
||||
gamedata.InitCfg(CFG_FREE_SHOP)
|
||||
gamedata.InitCfg(CFG_CHARGE_CONST)
|
||||
gamedata.InitCfg(CFG_CHARGE_GIFT)
|
||||
}
|
||||
|
||||
func GetMoneyCharge(ChargeId int) float64 {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_CHARGE, ChargeId)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetFloatValue(data, "Money")
|
||||
}
|
||||
|
||||
func GetDiamondShopReward(ChargeId int) []*item.Item {
|
||||
data, err := gamedata.GetData(CFG_DIAMOND_SHOP)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
for _, v := range data {
|
||||
if gamedata.GetIntValue(v, "ChargeId") == ChargeId {
|
||||
return []*item.Item{item.NewItem(item.ITEM_DIAMOND_ID, gamedata.GetIntValue(v, "Diamond"))}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetEnergyShopId(ChargeId int) int {
|
||||
data, err := gamedata.GetData(CFG_ENERGY_SHOP)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
for k, v := range data {
|
||||
if gamedata.GetIntValue(v, "ChargeId") == ChargeId {
|
||||
return GoUtil.Int(k)
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func GetEnergyShopReward(ChargeId int, First bool) []*item.Item {
|
||||
data, err := gamedata.GetData(CFG_ENERGY_SHOP)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
for _, v := range data {
|
||||
if gamedata.GetIntValue(v, "ChargeId") == ChargeId {
|
||||
Energy := gamedata.GetIntValue(v, "Energy")
|
||||
if !First {
|
||||
Energy += gamedata.GetIntValue(v, "FirstCharge")
|
||||
}
|
||||
return []*item.Item{item.NewItem(item.ITEM_ENERGY_ID, Energy)}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetSpecialShopReward(ChargeId int) []*item.Item {
|
||||
data, err := gamedata.GetData(CFG_SEPCIAL_SHOP)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
for _, v := range data {
|
||||
if gamedata.GetIntValue(v, "ChargeId") == ChargeId {
|
||||
return item.ParseItem(gamedata.GetValue(v, "Items"))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetSpecialShopType(ChargeId int) int {
|
||||
data, err := gamedata.GetData(CFG_SEPCIAL_SHOP)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
for _, v := range data {
|
||||
if gamedata.GetIntValue(v, "ChargeId") == ChargeId {
|
||||
return gamedata.GetIntValue(v, "Type")
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func GetFreeShopReward(ChargeId int) []*item.Item {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_FREE_SHOP, ChargeId)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
Item := gamedata.GetValue(data, "Items")
|
||||
return item.ParseItem(Item)
|
||||
}
|
||||
|
||||
func GetSpecialShopGrade(Money float64, Type int) int {
|
||||
type grade struct {
|
||||
id int
|
||||
money float64
|
||||
}
|
||||
data, err := gamedata.GetData(CFG_SEPCIAL_SHOP)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
l := make([]grade, 0)
|
||||
for _, v := range data {
|
||||
if gamedata.GetIntValue(v, "Type") != Type {
|
||||
continue
|
||||
}
|
||||
l = append(l, grade{
|
||||
id: gamedata.GetIntValue(v, "Grade"),
|
||||
money: GetMoneyCharge(gamedata.GetIntValue(v, "ChargeId")),
|
||||
})
|
||||
}
|
||||
sort.Slice(l, func(i, j int) bool {
|
||||
return l[i].money < l[j].money
|
||||
})
|
||||
|
||||
for _, v := range l {
|
||||
if Money < v.money {
|
||||
return v.id
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func GetUnlockShopLv() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_CHARGE_CONST, "shop_unlock_lv")
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
func GetSpecialShopCount() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_CHARGE_CONST, "special_shop_count")
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
func GetAdChargeId() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_CHARGE_CONST, "ad_charge_id")
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
func GetPiggyDuration() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_CHARGE_CONST, "pig_duration")
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
func GetPiggyMaxDia() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_CHARGE_CONST, "pig_max_diamond")
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
func GetPiggyRandDia() (int, int) {
|
||||
data, err := gamedata.GetDataByKey(CFG_CHARGE_CONST, "pig_diamond_rand")
|
||||
if err != nil {
|
||||
return 0, 0
|
||||
}
|
||||
str := gamedata.GetStringValue(data, "Value")
|
||||
strArr := strings.Split(str, ",")
|
||||
if len(strArr) != 2 {
|
||||
return 0, 0
|
||||
}
|
||||
return GoUtil.Int(strArr[0]), GoUtil.Int(strArr[1])
|
||||
}
|
||||
|
||||
func GetPiggyBankChargeId() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_CHARGE_CONST, "pig_charge_id")
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
func GetGiftReward(ChargeId int) []*item.Item {
|
||||
data, err := gamedata.GetData(CFG_CHARGE_GIFT)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
for _, v := range data {
|
||||
if gamedata.GetIntValue(v, "ChargeId") == ChargeId {
|
||||
return item.ParseItem(gamedata.GetValue(v, "Items"))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetGiftLimit(ChargeId int) int {
|
||||
data, err := gamedata.GetData(CFG_CHARGE_GIFT)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
for _, v := range data {
|
||||
if gamedata.GetIntValue(v, "ChargeId") == ChargeId {
|
||||
return gamedata.GetIntValue(v, "Count")
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
func GetGiftId(ChargeId int) int {
|
||||
data, err := gamedata.GetData(CFG_CHARGE_GIFT)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
for k, v := range data {
|
||||
if gamedata.GetIntValue(v, "ChargeId") == ChargeId {
|
||||
return GoUtil.Int(k)
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func GetChargeInfo(ChargeId int) (float64, string) {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_CHARGE, ChargeId)
|
||||
if err != nil {
|
||||
return 0, ""
|
||||
}
|
||||
return gamedata.GetFloatValue(data, "Money"), gamedata.GetStringValue(data, "Unit")
|
||||
}
|
||||
419
src/server/conf/charge/charge_cfg.go
Normal file
419
src/server/conf/charge/charge_cfg.go
Normal file
@ -0,0 +1,419 @@
|
||||
package chargeCfg
|
||||
|
||||
import (
|
||||
"server/game/mod/item"
|
||||
GoUtil "server/game_util"
|
||||
"server/gamedata"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"gitea.bywaystudios.com/pet_home/leaf/log"
|
||||
)
|
||||
|
||||
const (
|
||||
CFG_CHARGE = "Charge"
|
||||
CFG_DIAMOND_SHOP = "DiamondShop" // 钻石商店
|
||||
CFG_ENERGY_SHOP = "EnergyShop" // 体力商店
|
||||
CFG_SEPCIAL_SHOP = "SpecialShop" // 特惠商店
|
||||
CFG_FREE_SHOP = "FreeShop" // 免费商店
|
||||
CFG_CHARGE_CONST = "ChargeConst" // 充值常量配置
|
||||
CFG_CHARGE_GIFT = "ChargeGift" // 充值礼包
|
||||
CFG_CHARGE_WISH = "ChargeWish" // 许愿配置
|
||||
CFG_CHARGE_PETCOIN = "ChargePetCoin" // 宠物币充值配置
|
||||
CFG_CHARGE_AD = "ChargeAD" // 广告充值配置
|
||||
)
|
||||
|
||||
func init() {
|
||||
gamedata.InitCfg(CFG_CHARGE)
|
||||
gamedata.InitCfg(CFG_DIAMOND_SHOP)
|
||||
gamedata.InitCfg(CFG_ENERGY_SHOP)
|
||||
gamedata.InitCfg(CFG_SEPCIAL_SHOP)
|
||||
gamedata.InitCfg(CFG_FREE_SHOP)
|
||||
gamedata.InitCfg(CFG_CHARGE_CONST)
|
||||
gamedata.InitCfg(CFG_CHARGE_GIFT)
|
||||
gamedata.InitCfg(CFG_CHARGE_WISH)
|
||||
gamedata.InitCfg(CFG_CHARGE_PETCOIN)
|
||||
gamedata.InitCfg(CFG_CHARGE_AD)
|
||||
}
|
||||
|
||||
func GetADReward(ChargeId int) ([]*item.Item, int) {
|
||||
data, err := gamedata.GetData(CFG_CHARGE_AD)
|
||||
if err != nil {
|
||||
log.Debug("GetADReward err:%v, ChargeId=%d", err, ChargeId)
|
||||
return nil, 0
|
||||
}
|
||||
for _, v := range data {
|
||||
if gamedata.GetIntValue(v, "ChargeId") == ChargeId {
|
||||
return item.ParseItem(gamedata.GetValue(v, "Items")), gamedata.GetIntValue(v, "PetWork")
|
||||
}
|
||||
}
|
||||
return nil, 0
|
||||
}
|
||||
|
||||
func GetWeeklyDiscountDay() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_CHARGE_CONST, "weekly_discount_day")
|
||||
if err != nil {
|
||||
log.Debug("GetWeeklyDiscountDay err:%v", err)
|
||||
return -1
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
func GetMoneyCharge(ChargeId int) float64 {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_CHARGE, ChargeId)
|
||||
if err != nil {
|
||||
log.Debug("GetMoneyCharge err:%v, ChargeId=%d", err, ChargeId)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetFloatValue(data, "Money")
|
||||
}
|
||||
|
||||
func GetDiamondShopReward(ChargeId int) []*item.Item {
|
||||
data, err := gamedata.GetData(CFG_DIAMOND_SHOP)
|
||||
if err != nil {
|
||||
log.Debug("GetDiamondShopReward err:%v, ChargeId=%d", err, ChargeId)
|
||||
return nil
|
||||
}
|
||||
for _, v := range data {
|
||||
if gamedata.GetIntValue(v, "ChargeId") == ChargeId {
|
||||
return []*item.Item{item.NewItem(item.ITEM_DIAMOND_ID, gamedata.GetIntValue(v, "Diamond"))}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetEnergyShopId(ChargeId int) int {
|
||||
data, err := gamedata.GetData(CFG_ENERGY_SHOP)
|
||||
if err != nil {
|
||||
log.Debug("GetEnergyShopId err:%v, ChargeId=%d", err, ChargeId)
|
||||
return 0
|
||||
}
|
||||
for k, v := range data {
|
||||
if gamedata.GetIntValue(v, "ChargeId") == ChargeId {
|
||||
return GoUtil.Int(k)
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func GetWeeklyInfo(Pos int) (int, int) {
|
||||
data, err := gamedata.GetDataByKey(CFG_CHARGE_CONST, "weekly_chess_shop")
|
||||
if err != nil {
|
||||
log.Debug("GetWeeklyInfo err:%v, Pos=%d", err, Pos)
|
||||
return 0, 0
|
||||
}
|
||||
valueData, ok := data["Value"]
|
||||
if !ok {
|
||||
log.Debug("GetWeeklyInfo: Value field not found")
|
||||
return 0, 0
|
||||
}
|
||||
r, ok := valueData.([]interface{})
|
||||
if !ok {
|
||||
log.Debug("GetWeeklyInfo: Value is not []interface{}")
|
||||
return 0, 0
|
||||
}
|
||||
for _, v := range r {
|
||||
v1, ok := v.(map[string]interface{})
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
Id := GoUtil.Int(v1["Id"])
|
||||
if Id == Pos {
|
||||
return GoUtil.Int(v1["Discount"]), GoUtil.Int(v1["Limit"])
|
||||
}
|
||||
}
|
||||
return 0, 0
|
||||
}
|
||||
|
||||
func GetWeeklyInfoAll() map[int]gamedata.WeeklyDiscountInfo {
|
||||
data, err := gamedata.GetDataByKey(CFG_CHARGE_CONST, "weekly_chess_shop")
|
||||
if err != nil {
|
||||
log.Debug("GetWeeklyInfoAll err:%v", err)
|
||||
return nil
|
||||
}
|
||||
valueData, ok := data["Value"]
|
||||
if !ok {
|
||||
log.Debug("GetWeeklyInfoAll: Value field not found")
|
||||
return nil
|
||||
}
|
||||
r, ok := valueData.([]interface{})
|
||||
if !ok {
|
||||
log.Debug("GetWeeklyInfoAll: Value is not []interface{}")
|
||||
return nil
|
||||
}
|
||||
res := make(map[int]gamedata.WeeklyDiscountInfo, len(r))
|
||||
for _, v := range r {
|
||||
v1, ok := v.(map[string]interface{})
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
Id := GoUtil.Int(v1["Id"])
|
||||
res[Id] = gamedata.WeeklyDiscountInfo{
|
||||
Id: GoUtil.Int(v1["Id"]),
|
||||
Discount: GoUtil.Int(v1["Discount"]),
|
||||
WeeklyLimit: GoUtil.Int(v1["Limit"]),
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func GetEnergyShopReward(ChargeId int, First bool) []*item.Item {
|
||||
data, err := gamedata.GetData(CFG_ENERGY_SHOP)
|
||||
if err != nil {
|
||||
log.Debug("GetEnergyShopReward err:%v, ChargeId=%d", err, ChargeId)
|
||||
return nil
|
||||
}
|
||||
for _, v := range data {
|
||||
if gamedata.GetIntValue(v, "ChargeId") == ChargeId {
|
||||
Energy := gamedata.GetIntValue(v, "Energy")
|
||||
if !First {
|
||||
Energy += gamedata.GetIntValue(v, "FirstCharge")
|
||||
}
|
||||
return []*item.Item{item.NewItem(item.ITEM_ENERGY_ID, Energy)}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetSpecialShopReward(ChargeId int) []*item.Item {
|
||||
data, err := gamedata.GetData(CFG_SEPCIAL_SHOP)
|
||||
if err != nil {
|
||||
log.Debug("GetSpecialShopReward err:%v, ChargeId=%d", err, ChargeId)
|
||||
return nil
|
||||
}
|
||||
for _, v := range data {
|
||||
if gamedata.GetIntValue(v, "ChargeId") == ChargeId {
|
||||
return item.ParseItem(gamedata.GetValue(v, "Items"))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetSpecialShopType(ChargeId int) int {
|
||||
data, err := gamedata.GetData(CFG_SEPCIAL_SHOP)
|
||||
if err != nil {
|
||||
log.Debug("GetSpecialShopType err:%v, ChargeId=%d", err, ChargeId)
|
||||
return 0
|
||||
}
|
||||
for _, v := range data {
|
||||
if gamedata.GetIntValue(v, "ChargeId") == ChargeId {
|
||||
return gamedata.GetIntValue(v, "Type")
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func GetFreeShopReward(ChargeId int) []*item.Item {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_FREE_SHOP, ChargeId)
|
||||
if err != nil {
|
||||
log.Debug("GetFreeShopReward err:%v, ChargeId=%d", err, ChargeId)
|
||||
return nil
|
||||
}
|
||||
Item := gamedata.GetValue(data, "Items")
|
||||
return item.ParseItem(Item)
|
||||
}
|
||||
|
||||
func GetSpecialShopGrade(Money float64, Type int) int {
|
||||
type grade struct {
|
||||
id int
|
||||
money float64
|
||||
}
|
||||
data, err := gamedata.GetData(CFG_SEPCIAL_SHOP)
|
||||
if err != nil {
|
||||
log.Debug("GetSpecialShopGrade err:%v, Money=%.2f, Type=%d", err, Money, Type)
|
||||
return 0
|
||||
}
|
||||
l := make([]grade, 0, len(data))
|
||||
for _, v := range data {
|
||||
if gamedata.GetIntValue(v, "Type") != Type {
|
||||
continue
|
||||
}
|
||||
l = append(l, grade{
|
||||
id: gamedata.GetIntValue(v, "Grade"),
|
||||
money: GetMoneyCharge(gamedata.GetIntValue(v, "ChargeId")),
|
||||
})
|
||||
}
|
||||
sort.Slice(l, func(i, j int) bool {
|
||||
return l[i].money > l[j].money
|
||||
})
|
||||
|
||||
if len(l) == 0 {
|
||||
return 0
|
||||
}
|
||||
maxMoney := 0.0
|
||||
for _, v := range l {
|
||||
if Money >= v.money {
|
||||
maxMoney = max(maxMoney, v.money)
|
||||
}
|
||||
}
|
||||
for _, v := range l {
|
||||
if v.money == maxMoney {
|
||||
return v.id
|
||||
}
|
||||
}
|
||||
return l[0].id
|
||||
}
|
||||
|
||||
func GetUnlockShopLv() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_CHARGE_CONST, "shop_unlock_lv")
|
||||
if err != nil {
|
||||
log.Debug("GetUnlockShopLv err:%v", err)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
func GetSpecialShopCount() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_CHARGE_CONST, "special_shop_count")
|
||||
if err != nil {
|
||||
log.Debug("GetSpecialShopCount err:%v", err)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
func GetAdChargeId() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_CHARGE_CONST, "ad_charge_id")
|
||||
if err != nil {
|
||||
log.Debug("GetAdChargeId err:%v", err)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
func GetPiggyDuration() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_CHARGE_CONST, "pig_duration")
|
||||
if err != nil {
|
||||
log.Debug("GetPiggyDuration err:%v", err)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
func GetPiggyMaxDia() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_CHARGE_CONST, "pig_max_diamond")
|
||||
if err != nil {
|
||||
log.Debug("GetPiggyMaxDia err:%v", err)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
func GetPiggyRandDia() (int, int) {
|
||||
data, err := gamedata.GetDataByKey(CFG_CHARGE_CONST, "pig_diamond_rand")
|
||||
if err != nil {
|
||||
log.Debug("GetPiggyRandDia err:%v", err)
|
||||
return 0, 0
|
||||
}
|
||||
str := gamedata.GetStringValue(data, "Value")
|
||||
strArr := strings.Split(str, ",")
|
||||
if len(strArr) != 2 {
|
||||
return 0, 0
|
||||
}
|
||||
return GoUtil.Int(strArr[0]), GoUtil.Int(strArr[1])
|
||||
}
|
||||
|
||||
func GetPiggyBankChargeId() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_CHARGE_CONST, "pig_charge_id")
|
||||
if err != nil {
|
||||
log.Debug("GetPiggyBankChargeId err:%v", err)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
func GetGiftReward(ChargeId int) []*item.Item {
|
||||
data, err := gamedata.GetData(CFG_CHARGE_GIFT)
|
||||
if err != nil {
|
||||
log.Debug("GetGiftReward err:%v, ChargeId=%d", err, ChargeId)
|
||||
return nil
|
||||
}
|
||||
for _, v := range data {
|
||||
if gamedata.GetIntValue(v, "ChargeId") == ChargeId {
|
||||
return item.ParseItem(gamedata.GetValue(v, "Items"))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetGiftLimit(ChargeId int) int {
|
||||
data, err := gamedata.GetData(CFG_CHARGE_GIFT)
|
||||
if err != nil {
|
||||
log.Debug("GetGiftLimit err:%v, ChargeId=%d", err, ChargeId)
|
||||
return 0
|
||||
}
|
||||
for _, v := range data {
|
||||
if gamedata.GetIntValue(v, "ChargeId") == ChargeId {
|
||||
return gamedata.GetIntValue(v, "Count")
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
func GetGiftId(ChargeId int) int {
|
||||
data, err := gamedata.GetData(CFG_CHARGE_GIFT)
|
||||
if err != nil {
|
||||
log.Debug("GetGiftId err:%v, ChargeId=%d", err, ChargeId)
|
||||
return 0
|
||||
}
|
||||
for k, v := range data {
|
||||
if gamedata.GetIntValue(v, "ChargeId") == ChargeId {
|
||||
return GoUtil.Int(k)
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func GetChargeInfo(ChargeId int) (float64, string) {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_CHARGE, ChargeId)
|
||||
if err != nil {
|
||||
log.Debug("GetChargeInfo err:%v, ChargeId=%d", err, ChargeId)
|
||||
return 0, ""
|
||||
}
|
||||
return gamedata.GetFloatValue(data, "Money"), gamedata.GetStringValue(data, "Unit")
|
||||
}
|
||||
|
||||
func GetProduceName(ChargeId int) string {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_CHARGE, ChargeId)
|
||||
if err != nil {
|
||||
log.Debug("GetProduceName err:%v, ChargeId=%d", err, ChargeId)
|
||||
return ""
|
||||
}
|
||||
return gamedata.GetStringValue(data, "Remark")
|
||||
}
|
||||
|
||||
func GetWishCount(ItemId int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_CHARGE_WISH, ItemId)
|
||||
if err != nil {
|
||||
log.Debug("GetWishCount err:%v, ItemId=%d", err, ItemId)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Wish")
|
||||
}
|
||||
|
||||
func GetPetCoinShopReward(ChargeId int) []*item.Item {
|
||||
data, err := gamedata.GetData(CFG_CHARGE_PETCOIN)
|
||||
if err != nil {
|
||||
log.Debug("GetPetCoinShopReward err:%v, ChargeId=%d", err, ChargeId)
|
||||
return nil
|
||||
}
|
||||
for _, v := range data {
|
||||
if gamedata.GetIntValue(v, "ChargeId") == ChargeId {
|
||||
return gamedata.GetItemList(v, "Items")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetWeeklyDiscountStartEnd() (int64, int64) {
|
||||
data, err := gamedata.GetDataByKey(CFG_CHARGE_CONST, "weekly_discount_time")
|
||||
if err != nil {
|
||||
log.Debug("GetWeeklyDiscountStartEnd err:%v", err)
|
||||
return 0, 0
|
||||
}
|
||||
str := gamedata.GetStringValue(data, "Value")
|
||||
strArr := strings.Split(str, "|")
|
||||
if len(strArr) != 2 {
|
||||
return 0, 0
|
||||
}
|
||||
return GoUtil.ParseTime(strArr[0]), GoUtil.ParseTime(strArr[1])
|
||||
}
|
||||
68
src/server/conf/collect/collect_cfg.go
Normal file
68
src/server/conf/collect/collect_cfg.go
Normal file
@ -0,0 +1,68 @@
|
||||
package collectCfg
|
||||
|
||||
import (
|
||||
"server/game/mod/item"
|
||||
GoUtil "server/game_util"
|
||||
"server/gamedata"
|
||||
|
||||
"gitea.bywaystudios.com/pet_home/leaf/log"
|
||||
)
|
||||
|
||||
const (
|
||||
CFG_COLLECT = "Collect"
|
||||
CFG_COLLECT_JACKPOT = "CollectJackpot"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gamedata.InitCfg(CFG_COLLECT)
|
||||
gamedata.InitCfg(CFG_COLLECT_JACKPOT)
|
||||
}
|
||||
|
||||
func GetJackpotId() []int {
|
||||
data, err := gamedata.GetData(CFG_COLLECT_JACKPOT)
|
||||
if err != nil {
|
||||
log.Debug("GetJackpotId err:%v", err)
|
||||
return nil
|
||||
}
|
||||
ret := make([]int, 0, len(data))
|
||||
for k := range data {
|
||||
ret = append(ret, GoUtil.Int(k))
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func GetJackpotItems(Id int) []*item.Item {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_COLLECT_JACKPOT, Id)
|
||||
if err != nil {
|
||||
log.Debug("GetJackpotItems err:%v, Id=%d", err, Id)
|
||||
return nil
|
||||
}
|
||||
return gamedata.GetItemList(data, "Items")
|
||||
}
|
||||
|
||||
func GetRewardNeed(Id int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_COLLECT, Id)
|
||||
if err != nil {
|
||||
log.Debug("GetRewardNeed err:%v, Id=%d", err, Id)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Need")
|
||||
}
|
||||
|
||||
func GetRewardType(Id int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_COLLECT, Id)
|
||||
if err != nil {
|
||||
log.Debug("GetRewardType err:%v, Id=%d", err, Id)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Type")
|
||||
}
|
||||
|
||||
func GetRewardLen() int {
|
||||
data, err := gamedata.GetData(CFG_COLLECT)
|
||||
if err != nil {
|
||||
log.Debug("GetRewardLen err:%v", err)
|
||||
return 0
|
||||
}
|
||||
return len(data)
|
||||
}
|
||||
@ -7,18 +7,19 @@ import (
|
||||
|
||||
var (
|
||||
// log conf
|
||||
LogFlag = log.LstdFlags
|
||||
LogFlag = log.LstdFlags | log.Lmicroseconds
|
||||
|
||||
// gate conf
|
||||
PendingWriteNum = 2000
|
||||
MaxMsgLen uint32 = 16384 // 16KB
|
||||
PendingWriteNum = 2000 // 客户端链接的写入消息队列长度
|
||||
MaxMsgLen uint32 = 65536 // 16KB
|
||||
HTTPTimeout = 10 * time.Second
|
||||
LenMsgLen = 2
|
||||
LittleEndian = false
|
||||
|
||||
// skeleton conf
|
||||
GoLen = 10000
|
||||
TimerDispatcherLen = 10000
|
||||
AsynCallLen = 10000
|
||||
ChanRPCLen = 10000
|
||||
// 增加 goroutine 相关配置,避免 "Too many goroutines" 错误
|
||||
GoLen = 50000 // 从 10000 增加到 50000,控制并发 goroutine 数量
|
||||
TimerDispatcherLen = 50000 // 从 10000 增加到 50000,定时器队列长度
|
||||
AsynCallLen = 50000 // 从 10000 增加到 50000,异步调用队列长度
|
||||
ChanRPCLen = 50000 // 从 10000 增加到 50000,RPC 通道长度
|
||||
)
|
||||
|
||||
@ -1,89 +0,0 @@
|
||||
package dailyTaskCfg
|
||||
|
||||
import (
|
||||
"server/game/mod/item"
|
||||
"server/gamedata"
|
||||
"server/pkg/github.com/name5566/leaf/log"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const (
|
||||
DAILY_TASK_CONST = "DailyTaskConst"
|
||||
DAILY_TASK = "DailyTask"
|
||||
DAILY_TASK_ACTIVE = "DailyTaskActive"
|
||||
DAILY_TASK_JACKPOT = "DailyTaskJackpot"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gamedata.InitCfg(DAILY_TASK_CONST)
|
||||
gamedata.InitCfg(DAILY_TASK)
|
||||
gamedata.InitCfg(DAILY_TASK_ACTIVE)
|
||||
gamedata.InitCfg(DAILY_TASK_JACKPOT)
|
||||
}
|
||||
|
||||
// 获取任务列表
|
||||
func GetTaskList(Lv int) map[int]string {
|
||||
r := make(map[int]string)
|
||||
data, err := gamedata.GetData(DAILY_TASK)
|
||||
if err != nil {
|
||||
log.Debug("GetTaskList get data nil")
|
||||
return r
|
||||
}
|
||||
for k, v := range data {
|
||||
lv := gamedata.GetIntValue(v, "Lv")
|
||||
if Lv >= lv {
|
||||
k1, _ := strconv.Atoi(k)
|
||||
r[k1] = gamedata.GetStringValue(v, "Task")
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func GetTaskActiveId() []int {
|
||||
data, err := gamedata.GetData(DAILY_TASK_ACTIVE)
|
||||
if err != nil {
|
||||
log.Debug("GetTaskActiveId get data nil")
|
||||
return []int{}
|
||||
}
|
||||
r := make([]int, 0, len(data))
|
||||
for k := range data {
|
||||
Id, _ := strconv.Atoi(k)
|
||||
r = append(r, Id)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func GetTaskActiveById(Id int) int {
|
||||
data, err := gamedata.GetDataByIntKey(DAILY_TASK_ACTIVE, Id)
|
||||
if err != nil {
|
||||
log.Debug("GetTaskActiveById get data nil")
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Num")
|
||||
}
|
||||
|
||||
type Jackpot struct {
|
||||
Items []*item.Item
|
||||
Is_card int
|
||||
}
|
||||
|
||||
func GetTaskWeekJackpot() map[int]Jackpot {
|
||||
r := make(map[int]Jackpot)
|
||||
|
||||
data, err := gamedata.GetData(DAILY_TASK_JACKPOT)
|
||||
if err != nil {
|
||||
log.Debug("GetTaskWeekJackpot get data nil")
|
||||
return r
|
||||
}
|
||||
|
||||
for k, v := range data {
|
||||
Id, _ := strconv.Atoi(k)
|
||||
isCard := gamedata.GetIntValue(v, "CardPack")
|
||||
Item := item.ParseItem(gamedata.GetValue(v, "Items"))
|
||||
r[Id] = Jackpot{
|
||||
Items: Item,
|
||||
Is_card: isCard,
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
162
src/server/conf/daily_task/daily_task_cfg.go
Normal file
162
src/server/conf/daily_task/daily_task_cfg.go
Normal file
@ -0,0 +1,162 @@
|
||||
package dailyTaskCfg
|
||||
|
||||
import (
|
||||
"server/game/mod/item"
|
||||
"server/gamedata"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"gitea.bywaystudios.com/pet_home/leaf/log"
|
||||
)
|
||||
|
||||
const (
|
||||
DAILY_TASK_CONST = "DailyTaskConst"
|
||||
DAILY_TASK = "DailyTask"
|
||||
DAILY_TASK_ACTIVE = "DailyTaskActive"
|
||||
DAILY_TASK_JACKPOT = "DailyTaskJackpot"
|
||||
DAILY_TASK_REWARD = "DailyTaskReward"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gamedata.InitCfg(DAILY_TASK_CONST)
|
||||
gamedata.InitCfg(DAILY_TASK)
|
||||
gamedata.InitCfg(DAILY_TASK_ACTIVE)
|
||||
gamedata.InitCfg(DAILY_TASK_JACKPOT)
|
||||
gamedata.InitCfg(DAILY_TASK_REWARD)
|
||||
}
|
||||
|
||||
func GetDailyTaskReward(Id, activityId int) []*item.Item {
|
||||
data, err := gamedata.GetData(DAILY_TASK_REWARD)
|
||||
if err != nil {
|
||||
log.Debug("GetDailyTaskReward err:%v", err)
|
||||
return nil
|
||||
}
|
||||
for _, v := range data {
|
||||
sortId := gamedata.GetIntValue(v, "SortId")
|
||||
rewardGroupType := gamedata.GetIntValue(v, "RewardGroupType")
|
||||
if sortId == Id && rewardGroupType == activityId {
|
||||
items := gamedata.GetItemList(v, "ItemID")
|
||||
petCoinBase := gamedata.GetIntValue(v, "PetCoinBase")
|
||||
if petCoinBase > 0 {
|
||||
items = append(items, &item.Item{
|
||||
Id: item.ITEM_STAR_ID,
|
||||
Num: petCoinBase,
|
||||
})
|
||||
}
|
||||
return items
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetDailyTaskScore(Id, activityId int) int {
|
||||
data, err := gamedata.GetData(DAILY_TASK_REWARD)
|
||||
if err != nil {
|
||||
log.Debug("GetDailyTaskScore err:%v", err)
|
||||
return 0
|
||||
}
|
||||
for _, v := range data {
|
||||
sortId := gamedata.GetIntValue(v, "SortId")
|
||||
rewardGroupType := gamedata.GetIntValue(v, "RewardGroupType")
|
||||
if sortId == Id && rewardGroupType == activityId {
|
||||
return gamedata.GetIntValue(v, "ScoreReward")
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func GetActivityIds() []int {
|
||||
data, err := gamedata.GetDataByKey(DAILY_TASK_CONST, "RewardGroupType_const")
|
||||
if err != nil {
|
||||
log.Debug("GetActivityIds err:%v", err)
|
||||
return nil
|
||||
}
|
||||
str := gamedata.GetStringValue(data, "Value")
|
||||
strArr := strings.Split(str, "|")
|
||||
result := make([]int, 0, len(strArr))
|
||||
for _, v := range strArr {
|
||||
a, _ := strconv.Atoi(v)
|
||||
if a != 0 {
|
||||
result = append(result, a)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// 获取任务列表
|
||||
func GetTaskList(Lv int) map[int]string {
|
||||
data, err := gamedata.GetData(DAILY_TASK)
|
||||
if err != nil {
|
||||
log.Debug("GetTaskList err:%v, Lv=%d", err, Lv)
|
||||
return nil
|
||||
}
|
||||
r := make(map[int]string, len(data))
|
||||
for k, v := range data {
|
||||
lv := gamedata.GetIntValue(v, "Lv")
|
||||
if Lv >= lv {
|
||||
k1, err := strconv.Atoi(k)
|
||||
if err != nil {
|
||||
log.Debug("GetTaskList parse id err:%v, key=%s", err, k)
|
||||
continue
|
||||
}
|
||||
r[k1] = gamedata.GetStringValue(v, "Task")
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func GetTaskActiveId() []int {
|
||||
data, err := gamedata.GetData(DAILY_TASK_ACTIVE)
|
||||
if err != nil {
|
||||
log.Debug("GetTaskActiveId err:%v", err)
|
||||
return nil
|
||||
}
|
||||
r := make([]int, 0, len(data))
|
||||
for k := range data {
|
||||
Id, err := strconv.Atoi(k)
|
||||
if err != nil {
|
||||
log.Debug("GetTaskActiveId parse id err:%v, key=%s", err, k)
|
||||
continue
|
||||
}
|
||||
r = append(r, Id)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func GetTaskActiveById(Id int) int {
|
||||
data, err := gamedata.GetDataByIntKey(DAILY_TASK_ACTIVE, Id)
|
||||
if err != nil {
|
||||
log.Debug("GetTaskActiveById err:%v, Id=%d", err, Id)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Num")
|
||||
}
|
||||
|
||||
type Jackpot struct {
|
||||
Items []*item.Item
|
||||
Is_card int
|
||||
}
|
||||
|
||||
func GetTaskWeekJackpot() map[int]Jackpot {
|
||||
data, err := gamedata.GetData(DAILY_TASK_JACKPOT)
|
||||
if err != nil {
|
||||
log.Debug("GetTaskWeekJackpot err:%v", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
r := make(map[int]Jackpot, len(data))
|
||||
for k, v := range data {
|
||||
Id, err := strconv.Atoi(k)
|
||||
if err != nil {
|
||||
log.Debug("GetTaskWeekJackpot parse id err:%v, key=%s", err, k)
|
||||
continue
|
||||
}
|
||||
isCard := gamedata.GetIntValue(v, "CardPack")
|
||||
Item := item.ParseItem(gamedata.GetValue(v, "Items"))
|
||||
r[Id] = Jackpot{
|
||||
Items: Item,
|
||||
Is_card: isCard,
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
@ -1,95 +0,0 @@
|
||||
package decorateCfg
|
||||
|
||||
import (
|
||||
"server/game/mod/item"
|
||||
"server/gamedata"
|
||||
"server/pkg/github.com/name5566/leaf/log"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const (
|
||||
DECORATE_COST = "DecorateCost"
|
||||
INDOOR_PROGRESS = "IndoorProgress"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gamedata.InitCfg("DecorateCost")
|
||||
gamedata.InitCfg("IndoorProgress")
|
||||
}
|
||||
|
||||
func GetStarCost(AreaId, SortId int) int {
|
||||
data, err := gamedata.GetData(DECORATE_COST)
|
||||
if err != nil {
|
||||
log.Debug("DecorateCost GetStarCost not found")
|
||||
return 0
|
||||
}
|
||||
for _, v := range data {
|
||||
v1 := v.(map[string]interface{})
|
||||
if gamedata.ParseInt(v1["AreaId"]) == AreaId && gamedata.ParseInt(v1["SortId"]) == SortId {
|
||||
return gamedata.ParseInt(v1["CostCount"])
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func GetAreaId(id int) int {
|
||||
value, err := gamedata.GetDataByIntKey("DecorateCost", id)
|
||||
if err != nil {
|
||||
log.Debug("DecorateCost GetAreaId id:%v not found", id)
|
||||
return 0
|
||||
}
|
||||
return gamedata.ParseInt(value["AreaId"])
|
||||
}
|
||||
|
||||
func GetNextAreaId(AreaId, SortId int) int {
|
||||
data, err := gamedata.GetData(DECORATE_COST)
|
||||
if err != nil {
|
||||
log.Debug("DecorateCost GetStarCost not found")
|
||||
return 0
|
||||
}
|
||||
for k, v := range data {
|
||||
v1 := v.(map[string]interface{})
|
||||
if gamedata.ParseInt(v1["AreaId"]) == AreaId && gamedata.ParseInt(v1["SortId"]) == SortId {
|
||||
UnionKey, _ := strconv.Atoi(k)
|
||||
nextId := UnionKey + 1
|
||||
AreaId = GetAreaId(nextId)
|
||||
return AreaId
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func GetAllSortIdByAreaId(AreaId int) []int {
|
||||
data, err := gamedata.GetData(DECORATE_COST)
|
||||
if err != nil {
|
||||
log.Debug("DecorateCost GetAllSortIdByAreaId not found")
|
||||
return nil
|
||||
}
|
||||
var SortIdList []int
|
||||
for _, v := range data {
|
||||
v1 := v.(map[string]interface{})
|
||||
if gamedata.ParseInt(v1["AreaId"]) == AreaId {
|
||||
Sort := gamedata.ParseInt(v1["SortId"])
|
||||
if Sort == 0 {
|
||||
continue
|
||||
}
|
||||
SortIdList = append(SortIdList, Sort)
|
||||
}
|
||||
}
|
||||
return SortIdList
|
||||
}
|
||||
|
||||
func GetProgressReward(Scene, Lv int) []*item.Item {
|
||||
value, err := gamedata.GetData("IndoorProgress")
|
||||
if err != nil {
|
||||
log.Debug("IndoorProgress GetProgressReward not found")
|
||||
return nil
|
||||
}
|
||||
for _, v := range value {
|
||||
v1 := v.(map[string]interface{})
|
||||
if gamedata.ParseInt(v1["Scene"]) == Scene && gamedata.ParseInt(v1["Lv"]) == Lv {
|
||||
return item.ParseItem(v1["Item"])
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
256
src/server/conf/decorate/decorate_cfg.go
Normal file
256
src/server/conf/decorate/decorate_cfg.go
Normal file
@ -0,0 +1,256 @@
|
||||
package decorateCfg
|
||||
|
||||
import (
|
||||
"server/game/mod/item"
|
||||
"server/gamedata"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"gitea.bywaystudios.com/pet_home/leaf/log"
|
||||
)
|
||||
|
||||
const (
|
||||
DECORATE_COST = "DecorateCost"
|
||||
INDOOR_PROGRESS = "IndoorProgress"
|
||||
DECORATE_CONST = "DecorateConst"
|
||||
DECORATE_AREA = "DecorateArea" // 装饰区域
|
||||
)
|
||||
|
||||
func init() {
|
||||
gamedata.InitCfg(DECORATE_COST)
|
||||
gamedata.InitCfg(INDOOR_PROGRESS)
|
||||
gamedata.InitCfg(DECORATE_CONST)
|
||||
gamedata.InitCfg(DECORATE_AREA)
|
||||
}
|
||||
|
||||
func GetStarCost(AreaId, SortId int) int {
|
||||
data, err := gamedata.GetData(DECORATE_COST)
|
||||
if err != nil {
|
||||
log.Debug("GetStarCost err:%v, AreaId=%d, SortId=%d", err, AreaId, SortId)
|
||||
return 0
|
||||
}
|
||||
for _, v := range data {
|
||||
if gamedata.GetIntValue(v, "AreaId") == AreaId && gamedata.GetIntValue(v, "SortId") == SortId {
|
||||
return gamedata.GetIntValue(v, "CostCount")
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func GetStarCostByAreaId(AreaId int) int {
|
||||
data, err := gamedata.GetData(DECORATE_COST)
|
||||
if err != nil {
|
||||
log.Debug("GetStarCost err:%v, AreaId=%d", err, AreaId)
|
||||
return 0
|
||||
}
|
||||
var total int
|
||||
for _, v := range data {
|
||||
if gamedata.GetIntValue(v, "AreaId") == AreaId {
|
||||
total += gamedata.GetIntValue(v, "CostCount")
|
||||
}
|
||||
}
|
||||
return total
|
||||
}
|
||||
|
||||
func GetAreaId(id int) int {
|
||||
value, err := gamedata.GetDataByIntKey("DecorateCost", id)
|
||||
if err != nil {
|
||||
log.Debug("GetAreaId err:%v, id=%d", err, id)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(value, "AreaId")
|
||||
}
|
||||
|
||||
func GetNextAreaId(AreaId, SortId int) int {
|
||||
data, err := gamedata.GetData(DECORATE_COST)
|
||||
if err != nil {
|
||||
log.Debug("GetNextAreaId err:%v, AreaId=%d, SortId=%d", err, AreaId, SortId)
|
||||
return 0
|
||||
}
|
||||
for k, v := range data {
|
||||
if gamedata.GetIntValue(v, "AreaId") == AreaId && gamedata.GetIntValue(v, "SortId") == SortId {
|
||||
UnionKey, err := strconv.Atoi(k)
|
||||
if err != nil {
|
||||
log.Debug("GetNextAreaId parse key err:%v, key=%s", err, k)
|
||||
return 0
|
||||
}
|
||||
nextId := UnionKey + 1
|
||||
AreaId = GetAreaId(nextId)
|
||||
return AreaId
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func GetAllSortIdByAreaId(AreaId int) []int {
|
||||
data, err := gamedata.GetData(DECORATE_COST)
|
||||
if err != nil {
|
||||
log.Debug("GetAllSortIdByAreaId err:%v, AreaId=%d", err, AreaId)
|
||||
return nil
|
||||
}
|
||||
SortIdList := make([]int, 0, len(data)/5)
|
||||
for _, v := range data {
|
||||
if gamedata.GetIntValue(v, "AreaId") == AreaId {
|
||||
Sort := gamedata.GetIntValue(v, "SortId")
|
||||
if Sort == 0 {
|
||||
continue
|
||||
}
|
||||
SortIdList = append(SortIdList, Sort)
|
||||
}
|
||||
}
|
||||
return SortIdList
|
||||
}
|
||||
|
||||
func GetProgressReward(Scene, Lv int) []*item.Item {
|
||||
value, err := gamedata.GetData(INDOOR_PROGRESS)
|
||||
if err != nil {
|
||||
log.Debug("GetProgressReward err:%v, Scene=%d, Lv=%d", err, Scene, Lv)
|
||||
return nil
|
||||
}
|
||||
for _, v := range value {
|
||||
if gamedata.GetIntValue(v, "Scene") == Scene && gamedata.GetIntValue(v, "Lv") == Lv {
|
||||
return gamedata.GetItemList(v, "AreaReward")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetDecoarteReward(Scene int, Lv int) []*item.Item {
|
||||
value, err := gamedata.GetData(INDOOR_PROGRESS)
|
||||
if err != nil {
|
||||
log.Debug("GetDecoarteReward err:%v, Scene=%d, Lv=%d", err, Scene, Lv)
|
||||
return nil
|
||||
}
|
||||
for _, v := range value {
|
||||
if gamedata.GetIntValue(v, "Scene") == Scene && gamedata.GetIntValue(v, "Lv") == Lv {
|
||||
return gamedata.GetItemList(v, "Item")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetAreaReward(AreaId int) []*item.Item {
|
||||
value, err := gamedata.GetDataByIntKey(DECORATE_AREA, AreaId)
|
||||
if err != nil {
|
||||
log.Debug("GetAreaReward err:%v, AreaId=%d", err, AreaId)
|
||||
return nil
|
||||
}
|
||||
return gamedata.GetItemList(value, "Items")
|
||||
}
|
||||
|
||||
// 获取一键装饰的解锁等级
|
||||
func GetOneKeyDecorateUnlockLv() int {
|
||||
data, err := gamedata.GetDataByKey(DECORATE_CONST, "OneKey")
|
||||
if err != nil {
|
||||
log.Debug("GetOneKeyDecorateUnlockLv err:%v", err)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
// 获取每次装饰增加的体力值
|
||||
func GetDecorateAddEnergy() int {
|
||||
data, err := gamedata.GetDataByKey(DECORATE_CONST, "AddEnergy")
|
||||
if err != nil {
|
||||
log.Debug("GetDecorateAddEnergy err:%v", err)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
func GetAreaPerPExp(AreaId int) int {
|
||||
data, err := gamedata.GetDataByIntKey(DECORATE_AREA, AreaId)
|
||||
if err != nil {
|
||||
log.Debug("GetAreaPerPExp err:%v, AreaId=%d", err, AreaId)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "PerPExp")
|
||||
}
|
||||
|
||||
func GetDecoratePExp(AreaId, SortId int) int {
|
||||
data, err := gamedata.GetData(DECORATE_COST)
|
||||
if err != nil {
|
||||
log.Debug("GetDecoratePExp err:%v, AreaId=%d, SortId=%d", err, AreaId, SortId)
|
||||
return 0
|
||||
}
|
||||
for _, v := range data {
|
||||
if gamedata.GetIntValue(v, "AreaId") == AreaId && gamedata.GetIntValue(v, "SortId") == SortId {
|
||||
return gamedata.GetIntValue(v, "PetExp")
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func GetAllPartId() []int {
|
||||
data, err := gamedata.GetDataByKey(DECORATE_CONST, "AllPartId")
|
||||
if err != nil {
|
||||
log.Debug("GetAllPartId err:%v", err)
|
||||
return nil
|
||||
}
|
||||
str := gamedata.GetStringValue(data, "Value")
|
||||
r1 := strings.Split(str, "|")
|
||||
PartIdList := make([]int, 0, len(r1))
|
||||
for _, v := range r1 {
|
||||
id, err := strconv.Atoi(v)
|
||||
if err != nil {
|
||||
log.Debug("GetAllPartId parse id err:%v, v=%s", err, v)
|
||||
continue
|
||||
}
|
||||
PartIdList = append(PartIdList, id)
|
||||
}
|
||||
return PartIdList
|
||||
}
|
||||
|
||||
func GetIdBySenceAndLv(Sence, Lv int) int {
|
||||
data, err := gamedata.GetData(INDOOR_PROGRESS)
|
||||
if err != nil {
|
||||
log.Debug("GetIdBySenceAndLv err:%v, Sence=%d, Lv=%d", err, Sence, Lv)
|
||||
return 0
|
||||
}
|
||||
for k, v := range data {
|
||||
if gamedata.GetIntValue(v, "Scene") == Sence && gamedata.GetIntValue(v, "Lv") == Lv {
|
||||
id, err := strconv.Atoi(k)
|
||||
if err != nil {
|
||||
log.Debug("GetIdBySenceAndLv parse id err:%v, key=%s", err, k)
|
||||
return 0
|
||||
}
|
||||
return id
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func GetPartNumByAreaId(AreaId int) map[int]int {
|
||||
data, err := gamedata.GetData(INDOOR_PROGRESS)
|
||||
if err != nil {
|
||||
log.Debug("GetPartNumByAreaId err:%v, AreaId=%d", err, AreaId)
|
||||
return nil
|
||||
}
|
||||
res := make(map[int]int, len(data))
|
||||
for k, v := range data {
|
||||
Sence := gamedata.GetIntValue(v, "Scene")
|
||||
if Sence != AreaId {
|
||||
continue
|
||||
}
|
||||
id, err := strconv.Atoi(k)
|
||||
if err != nil {
|
||||
log.Debug("GetPartNumByAreaId parse id err:%v, key=%s", err, k)
|
||||
continue
|
||||
}
|
||||
PartNum := gamedata.GetIntValue(v, "Part")
|
||||
if PartNum == 0 {
|
||||
continue
|
||||
}
|
||||
res[id] = PartNum
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func GetAreaIdByIndoorId(IndoorId int) int {
|
||||
data, err := gamedata.GetDataByIntKey(INDOOR_PROGRESS, IndoorId)
|
||||
if err != nil {
|
||||
log.Debug("GetAreaIdByIndoorId err:%v, IndoorId=%d", err, IndoorId)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Scene")
|
||||
}
|
||||
54
src/server/conf/emoji/emoji_cfg.go
Normal file
54
src/server/conf/emoji/emoji_cfg.go
Normal file
@ -0,0 +1,54 @@
|
||||
package emojiCfg
|
||||
|
||||
import (
|
||||
GoUtil "server/game_util"
|
||||
"server/gamedata"
|
||||
|
||||
"gitea.bywaystudios.com/pet_home/leaf/log"
|
||||
)
|
||||
|
||||
const (
|
||||
CFG_EMOJI = "Emoji"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gamedata.InitCfg(CFG_EMOJI)
|
||||
}
|
||||
|
||||
func GetInitList() []int {
|
||||
data, err := gamedata.GetData(CFG_EMOJI)
|
||||
if err != nil {
|
||||
log.Debug("GetInitList err:%v", err)
|
||||
return nil
|
||||
}
|
||||
ret := make([]int, 0, len(data))
|
||||
for k, v := range data {
|
||||
Init := gamedata.GetIntValue(v, "Init")
|
||||
if Init == 1 {
|
||||
ret = append(ret, GoUtil.Int(k))
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func GetAllList() []int {
|
||||
data, err := gamedata.GetData(CFG_EMOJI)
|
||||
if err != nil {
|
||||
log.Debug("GetAllList err:%v", err)
|
||||
return nil
|
||||
}
|
||||
ret := make([]int, 0, len(data))
|
||||
for k := range data {
|
||||
ret = append(ret, GoUtil.Int(k))
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func GetEmojiName(Id int) string {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_EMOJI, Id)
|
||||
if err != nil {
|
||||
log.Debug("GetEmojiName err:%v, Id=%d", err, Id)
|
||||
return ""
|
||||
}
|
||||
return gamedata.GetStringValue(data, "Name")
|
||||
}
|
||||
@ -3,6 +3,8 @@ package endlessCfg
|
||||
import (
|
||||
"server/game/mod/item"
|
||||
"server/gamedata"
|
||||
|
||||
"gitea.bywaystudios.com/pet_home/leaf/log"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -15,14 +17,15 @@ func init() {
|
||||
gamedata.InitCfg(CFG_ENDLESS_JACKPOT)
|
||||
}
|
||||
|
||||
func GetDiamond(Money float64) float64 {
|
||||
func GetEnergy(Money float64) float64 {
|
||||
data, err := gamedata.GetData(CFG_ENDLESS)
|
||||
if err != nil {
|
||||
log.Debug("GetEnergy err:%v, Money=%.2f", err, Money)
|
||||
return 0
|
||||
}
|
||||
for _, v := range data {
|
||||
if Money == gamedata.GetFloatValue(v, "Money") {
|
||||
return gamedata.GetFloatValue(v, "Diamond")
|
||||
return gamedata.GetFloatValue(v, "Energy")
|
||||
}
|
||||
}
|
||||
return 0
|
||||
@ -31,6 +34,7 @@ func GetDiamond(Money float64) float64 {
|
||||
func NextMoney(Money float64) float64 {
|
||||
data, err := gamedata.GetData(CFG_ENDLESS)
|
||||
if err != nil {
|
||||
log.Debug("NextMoney err:%v, Money=%.2f", err, Money)
|
||||
return 0
|
||||
}
|
||||
for _, v := range data {
|
||||
@ -44,6 +48,7 @@ func NextMoney(Money float64) float64 {
|
||||
func GetChargeId(Money float64) int {
|
||||
data, err := gamedata.GetData(CFG_ENDLESS)
|
||||
if err != nil {
|
||||
log.Debug("GetChargeId err:%v, Money=%.2f", err, Money)
|
||||
return 0
|
||||
}
|
||||
for _, v := range data {
|
||||
@ -54,27 +59,29 @@ func GetChargeId(Money float64) int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func GetPerDiamond(Id int) float64 {
|
||||
func GetPerEnergy(Id int) float64 {
|
||||
data, err := gamedata.GetData(CFG_ENDLESS_JACKPOT)
|
||||
if err != nil {
|
||||
log.Debug("GetPerEnergy err:%v, Id=%d", err, Id)
|
||||
return 0
|
||||
}
|
||||
for _, v := range data {
|
||||
if Id == gamedata.GetIntValue(v, "ItemId") {
|
||||
return gamedata.GetFloatValue(v, "Diamond")
|
||||
return gamedata.GetFloatValue(v, "Energy")
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func GetItemId(Diamond float64, Type int) []int {
|
||||
func GetItemId(Energy float64, Type, Lv int) []int {
|
||||
data, err := gamedata.GetData(CFG_ENDLESS_JACKPOT)
|
||||
if err != nil {
|
||||
log.Debug("GetItemId err:%v, Energy=%.2f, Type=%d, Lv=%d", err, Energy, Type, Lv)
|
||||
return nil
|
||||
}
|
||||
var ItemId []int
|
||||
ItemId := make([]int, 0, len(data))
|
||||
for _, v := range data {
|
||||
if Diamond >= gamedata.GetFloatValue(v, "Diamond") && Type != gamedata.GetIntValue(v, "Type") && gamedata.GetIntValue(v, "ItemId") != item.ITEM_ENERGY_ID {
|
||||
if Lv >= gamedata.GetIntValue(v, "Lv") && Energy >= gamedata.GetFloatValue(v, "Energy") && Type != gamedata.GetIntValue(v, "Type") && gamedata.GetIntValue(v, "ItemId") != item.ITEM_ENERGY_ID {
|
||||
ItemId = append(ItemId, gamedata.GetIntValue(v, "ItemId"))
|
||||
}
|
||||
}
|
||||
@ -84,6 +91,7 @@ func GetItemId(Diamond float64, Type int) []int {
|
||||
func GetType(ItemId int) int {
|
||||
data, err := gamedata.GetData(CFG_ENDLESS_JACKPOT)
|
||||
if err != nil {
|
||||
log.Debug("GetType err:%v, ItemId=%d", err, ItemId)
|
||||
return 0
|
||||
}
|
||||
for _, v := range data {
|
||||
@ -94,14 +102,15 @@ func GetType(ItemId int) int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func GeDiamondByItemId(ItemId int) float64 {
|
||||
func GetEnergyByItemId(ItemId int) float64 {
|
||||
data, err := gamedata.GetData(CFG_ENDLESS_JACKPOT)
|
||||
if err != nil {
|
||||
log.Debug("GetEnergyByItemId err:%v, ItemId=%d", err, ItemId)
|
||||
return 0
|
||||
}
|
||||
for _, v := range data {
|
||||
if ItemId == gamedata.GetIntValue(v, "ItemId") {
|
||||
return gamedata.GetFloatValue(v, "Diamond")
|
||||
return gamedata.GetFloatValue(v, "Energy")
|
||||
}
|
||||
}
|
||||
return 0
|
||||
@ -1,42 +0,0 @@
|
||||
package faceCfg
|
||||
|
||||
import (
|
||||
"server/gamedata"
|
||||
"server/pkg/github.com/name5566/leaf/log"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const (
|
||||
CFG_FACE = "Face"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gamedata.InitCfg(CFG_FACE)
|
||||
}
|
||||
|
||||
func GetInitList() []int {
|
||||
data, err := gamedata.GetData(CFG_FACE)
|
||||
if err != nil {
|
||||
log.Debug("GetInitList err: %v", err)
|
||||
return nil
|
||||
}
|
||||
r := make([]int, 0)
|
||||
for k, v := range data {
|
||||
IsInit := gamedata.GetIntValue(v, "Init")
|
||||
if IsInit == 1 {
|
||||
k, _ := strconv.Atoi(k)
|
||||
r = append(r, k)
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func CheckExist(Id int) bool {
|
||||
data, err := gamedata.GetData(CFG_FACE)
|
||||
if err != nil {
|
||||
log.Debug("CheckExist err: %v", err)
|
||||
return false
|
||||
}
|
||||
_, ok := data[strconv.Itoa(Id)]
|
||||
return ok
|
||||
}
|
||||
75
src/server/conf/face/face_cfg.go
Normal file
75
src/server/conf/face/face_cfg.go
Normal file
@ -0,0 +1,75 @@
|
||||
package faceCfg
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"server/gamedata"
|
||||
"strconv"
|
||||
|
||||
"gitea.bywaystudios.com/pet_home/leaf/log"
|
||||
)
|
||||
|
||||
const (
|
||||
CFG_FACE = "Face"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gamedata.InitCfg(CFG_FACE)
|
||||
}
|
||||
|
||||
func GetInitList() []int {
|
||||
data, err := gamedata.GetData(CFG_FACE)
|
||||
if err != nil {
|
||||
log.Debug("GetInitList err:%v", err)
|
||||
return nil
|
||||
}
|
||||
r := make([]int, 0, len(data))
|
||||
for k, v := range data {
|
||||
IsInit := gamedata.GetIntValue(v, "Init")
|
||||
if IsInit == 1 {
|
||||
id, err := strconv.Atoi(k)
|
||||
if err != nil {
|
||||
log.Debug("GetInitList parse id err:%v, key=%s", err, k)
|
||||
continue
|
||||
}
|
||||
r = append(r, id)
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func GetRandInitId() int {
|
||||
list := GetInitList()
|
||||
if len(list) == 0 {
|
||||
return 0
|
||||
}
|
||||
index := rand.Intn(len(list))
|
||||
return list[index]
|
||||
}
|
||||
|
||||
func CheckExist(Id int) bool {
|
||||
data, err := gamedata.GetData(CFG_FACE)
|
||||
if err != nil {
|
||||
log.Debug("CheckExist err:%v, Id=%d", err, Id)
|
||||
return false
|
||||
}
|
||||
_, ok := data[strconv.Itoa(Id)]
|
||||
return ok
|
||||
}
|
||||
|
||||
func GetAllId() []int {
|
||||
data, err := gamedata.GetData(CFG_FACE)
|
||||
if err != nil {
|
||||
log.Debug("GetAllId err:%v", err)
|
||||
return nil
|
||||
}
|
||||
r := make([]int, 0, len(data))
|
||||
for k := range data {
|
||||
Id, err := strconv.Atoi(k)
|
||||
if err != nil {
|
||||
log.Debug("GetAllId parse id err:%v, key=%s", err, k)
|
||||
continue
|
||||
}
|
||||
r = append(r, Id)
|
||||
}
|
||||
return r
|
||||
}
|
||||
71
src/server/conf/friend/friend_cfg.go
Normal file
71
src/server/conf/friend/friend_cfg.go
Normal file
@ -0,0 +1,71 @@
|
||||
package friendCfg
|
||||
|
||||
import (
|
||||
"server/gamedata"
|
||||
|
||||
"gitea.bywaystudios.com/pet_home/leaf/log"
|
||||
)
|
||||
|
||||
const (
|
||||
CFG_NPC_FRIENDS = "NPCFriends"
|
||||
CFG_CONST = "FriendConst"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gamedata.InitCfg(CFG_NPC_FRIENDS)
|
||||
gamedata.InitCfg(CFG_CONST)
|
||||
}
|
||||
|
||||
func IsNpcFriend(Id int) bool {
|
||||
_, err := gamedata.GetDataByIntKey(CFG_NPC_FRIENDS, Id)
|
||||
if err != nil {
|
||||
log.Debug("IsNpcFriend err:%v, Id=%d", err, Id)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func GetFriendSponsorNum() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_CONST, "friend_energy_bonus")
|
||||
if err != nil {
|
||||
log.Debug("GetFriendSponsorNum err:%v", err)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
func GetFriendLimitNum() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_CONST, "friend_limit")
|
||||
if err != nil {
|
||||
log.Debug("GetFriendLimitNum err:%v", err)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
func GetDailyRecommendLimit() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_CONST, "friend_daily_recommend_limit")
|
||||
if err != nil {
|
||||
log.Debug("GetDailyRecommendLimit err:%v", err)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
func GetApplyListLimit() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_CONST, "friend_apply_list_limit")
|
||||
if err != nil {
|
||||
log.Debug("GetApplyListLimit err:%v", err)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
func GetDailyGetApplyLimit() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_CONST, "friend_daily_get_apply_limit")
|
||||
if err != nil {
|
||||
log.Debug("GetDailyGetApplyLimit err:%v", err)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
87
src/server/conf/friend_treasure/friend_treasure_cfg.go
Normal file
87
src/server/conf/friend_treasure/friend_treasure_cfg.go
Normal file
@ -0,0 +1,87 @@
|
||||
package friendTreasureCfg
|
||||
|
||||
import (
|
||||
"server/game/mod/item"
|
||||
GoUtil "server/game_util"
|
||||
"server/gamedata"
|
||||
)
|
||||
|
||||
const (
|
||||
CFG_FRIEND_TREASURE_PROB = "FriendTreasureProb"
|
||||
CFG_FRIEND_TREASURE_CHEST = "FriendTreasureChest"
|
||||
CFG_FRIEND_TREASURE_CONST = "FriendTreasureConst"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gamedata.InitCfg(CFG_FRIEND_TREASURE_PROB)
|
||||
gamedata.InitCfg(CFG_FRIEND_TREASURE_CHEST)
|
||||
gamedata.InitCfg(CFG_FRIEND_TREASURE_CONST)
|
||||
}
|
||||
|
||||
func GetBigReward() []*item.Item {
|
||||
data, err := gamedata.GetDataByKey(CFG_FRIEND_TREASURE_CONST, "big_reward")
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return gamedata.GetItemList(data, "Value")
|
||||
}
|
||||
|
||||
func GetFriendTreasureProb(Num int) map[int]int {
|
||||
data, err := gamedata.GetData(CFG_FRIEND_TREASURE_PROB)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
ProbMap := make(map[int]int)
|
||||
for k, v := range data {
|
||||
Id := GoUtil.Int(k)
|
||||
Prob := gamedata.GetIntValue(v, "Prob")
|
||||
ProbMap[Id] = Prob
|
||||
}
|
||||
AddProb := 0
|
||||
n := 0
|
||||
for k, v := range ProbMap {
|
||||
if k > Num {
|
||||
AddProb += v
|
||||
n++
|
||||
ProbMap[k] = 0
|
||||
}
|
||||
}
|
||||
PerProb := AddProb / n
|
||||
for k, v := range ProbMap {
|
||||
if k <= Num && k != 1 {
|
||||
ProbMap[k] = v + PerProb
|
||||
}
|
||||
}
|
||||
return ProbMap
|
||||
}
|
||||
|
||||
func GetProbAdd(Id int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_FRIEND_TREASURE_PROB, Id)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Add")
|
||||
}
|
||||
|
||||
func GetChestProb() map[int]int {
|
||||
data, err := gamedata.GetData(CFG_FRIEND_TREASURE_CHEST)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
ProbMap := make(map[int]int)
|
||||
for k, v := range data {
|
||||
Id := GoUtil.Int(k)
|
||||
Prob := gamedata.GetIntValue(v, "Prob")
|
||||
ProbMap[Id] = Prob
|
||||
}
|
||||
return ProbMap
|
||||
}
|
||||
|
||||
func GetChestItems(Id int) []*item.Item {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_FRIEND_TREASURE_CHEST, Id)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return gamedata.GetItemList(data, "Items")
|
||||
}
|
||||
73
src/server/conf/fur/fur_cfg.go
Normal file
73
src/server/conf/fur/fur_cfg.go
Normal file
@ -0,0 +1,73 @@
|
||||
package fur_cfg
|
||||
|
||||
import (
|
||||
"server/game/mod/item"
|
||||
"server/gamedata"
|
||||
)
|
||||
|
||||
const (
|
||||
CFG_FUR_CONST = "FurShopConst"
|
||||
CFG_FUR_SHOP = "FurShop"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gamedata.InitCfg(CFG_FUR_CONST)
|
||||
gamedata.InitCfg(CFG_FUR_SHOP)
|
||||
}
|
||||
|
||||
func GetFurShopCost(id int) []*item.Item {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_FUR_SHOP, id)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return gamedata.GetItemList(data, "Cost")
|
||||
}
|
||||
|
||||
func GetFurShopFreeTimes() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_FUR_CONST, "free_unlock")
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
func GetFurShopTag(id int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_FUR_SHOP, id)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "TAG")
|
||||
}
|
||||
|
||||
func GetFurShopName(id int) string {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_FUR_SHOP, id)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return gamedata.GetStringValue(data, "Name")
|
||||
}
|
||||
|
||||
func GetFurShopItem(id int) []*item.Item {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_FUR_SHOP, id)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
itemId := gamedata.GetIntValue(data, "ItemID")
|
||||
if itemId == 0 {
|
||||
return nil
|
||||
}
|
||||
return []*item.Item{
|
||||
{
|
||||
Id: itemId,
|
||||
Num: 1,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func GetFurShopCostNum(id int) int {
|
||||
item := GetFurShopCost(id)
|
||||
if len(item) == 0 {
|
||||
return 0
|
||||
}
|
||||
return item[0].Num
|
||||
}
|
||||
119
src/server/conf/guess_color/guess_color_cfg.go
Normal file
119
src/server/conf/guess_color/guess_color_cfg.go
Normal file
@ -0,0 +1,119 @@
|
||||
package guesscolorCfg
|
||||
|
||||
import (
|
||||
"server/game/mod/item"
|
||||
GoUtil "server/game_util"
|
||||
"server/gamedata"
|
||||
"strings"
|
||||
|
||||
"gitea.bywaystudios.com/pet_home/leaf/log"
|
||||
)
|
||||
|
||||
const (
|
||||
CFG_GUESS_COLOR_TEMPLATE = "GuessColorTemplate"
|
||||
CFG_GUESS_COLOR_REWARD = "GuessColorReward"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gamedata.InitCfg(CFG_GUESS_COLOR_TEMPLATE)
|
||||
gamedata.InitCfg(CFG_GUESS_COLOR_REWARD)
|
||||
}
|
||||
|
||||
func GetFirstPass(Id int) map[int]int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_GUESS_COLOR_TEMPLATE, Id)
|
||||
if err != nil {
|
||||
log.Debug("GetFirstPass err:%v, Id=%d", err, Id)
|
||||
return nil
|
||||
}
|
||||
str := gamedata.GetStringValue(data, "FirstPass")
|
||||
arr := strings.Split(str, "|")
|
||||
ret := make(map[int]int, len(arr))
|
||||
for k, v := range arr {
|
||||
ret[k+1] = GoUtil.Int(v)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func GetLoseItem(Id int) []*item.Item {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_GUESS_COLOR_TEMPLATE, Id)
|
||||
if err != nil {
|
||||
log.Debug("GetLoseItem err:%v, Id=%d", err, Id)
|
||||
return nil
|
||||
}
|
||||
return gamedata.GetItemList(data, "ItemCost")
|
||||
}
|
||||
|
||||
func GetFirstItem(Id int) []*item.Item {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_GUESS_COLOR_TEMPLATE, Id)
|
||||
if err != nil {
|
||||
log.Debug("GetFirstItem err:%v, Id=%d", err, Id)
|
||||
return nil
|
||||
}
|
||||
return gamedata.GetItemList(data, "FirstItem")
|
||||
}
|
||||
|
||||
func GetActivityItemId(Id int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_GUESS_COLOR_TEMPLATE, Id)
|
||||
if err != nil {
|
||||
log.Debug("GetActivityItemId err:%v, Id=%d", err, Id)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "ItemId")
|
||||
}
|
||||
|
||||
func GetRewardItem(Id int, Type int) []*item.Item {
|
||||
data, err := gamedata.GetData(CFG_GUESS_COLOR_REWARD)
|
||||
if err != nil {
|
||||
log.Debug("GetRewardItem err:%v, Id=%d, Type=%d", err, Id, Type)
|
||||
return nil
|
||||
}
|
||||
for k, v := range data {
|
||||
min := GoUtil.Int(k)
|
||||
max := gamedata.GetIntValue(v, "Max")
|
||||
if Id >= min && Id <= max {
|
||||
if Type == 1 {
|
||||
return gamedata.GetItemList(v, "Items1")
|
||||
}
|
||||
return gamedata.GetItemList(v, "Items2")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetPassNum(Id int) int {
|
||||
data, err := gamedata.GetData(CFG_GUESS_COLOR_REWARD)
|
||||
if err != nil {
|
||||
log.Debug("GetPassNum err:%v, Id=%d", err, Id)
|
||||
return 0
|
||||
}
|
||||
for k, v := range data {
|
||||
min := GoUtil.Int(k)
|
||||
max := gamedata.GetIntValue(v, "Max")
|
||||
if Id >= min && Id <= max {
|
||||
return gamedata.GetIntValue(v, "Num")
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func GetWinTime(Id int) int {
|
||||
data, err := gamedata.GetData(CFG_GUESS_COLOR_REWARD)
|
||||
if err != nil {
|
||||
log.Debug("GetWinTime err:%v, Id=%d", err, Id)
|
||||
return 0
|
||||
}
|
||||
for k, v := range data {
|
||||
min := GoUtil.Int(k)
|
||||
max := gamedata.GetIntValue(v, "Max")
|
||||
if Id >= min && Id <= max {
|
||||
Type := gamedata.GetIntValue(v, "Type")
|
||||
if Type == 1 {
|
||||
return gamedata.GetIntValue(v, "Win")
|
||||
}
|
||||
str := gamedata.GetStringValue(v, "Win")
|
||||
arr := strings.Split(str, "|")
|
||||
return GoUtil.RandNum(GoUtil.Int(arr[0]), GoUtil.Int(arr[1]))
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
25
src/server/conf/guide/guide_cfg.go
Normal file
25
src/server/conf/guide/guide_cfg.go
Normal file
@ -0,0 +1,25 @@
|
||||
package guidecfg
|
||||
|
||||
import (
|
||||
"server/game/mod/item"
|
||||
"server/gamedata"
|
||||
|
||||
"gitea.bywaystudios.com/pet_home/leaf/log"
|
||||
)
|
||||
|
||||
const (
|
||||
GUIDE_REWARD = "GuideReward"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gamedata.InitCfg(GUIDE_REWARD)
|
||||
}
|
||||
|
||||
func GetGuideReward(Id int) ([]*item.Item, int) {
|
||||
data, err := gamedata.GetDataByIntKey(GUIDE_REWARD, Id)
|
||||
if err != nil {
|
||||
log.Debug("GetGuideReward err:%v, Id=%d", err, Id)
|
||||
return nil, 0
|
||||
}
|
||||
return item.ParseItem(gamedata.GetValue(data, "Items")), gamedata.GetIntValue(data, "Num")
|
||||
}
|
||||
120
src/server/conf/guide_task/guide_task_cfg.go
Normal file
120
src/server/conf/guide_task/guide_task_cfg.go
Normal file
@ -0,0 +1,120 @@
|
||||
package GuideTaskCfg
|
||||
|
||||
import (
|
||||
"server/game/mod/item"
|
||||
GoUtil "server/game_util"
|
||||
"server/gamedata"
|
||||
"strconv"
|
||||
|
||||
"gitea.bywaystudios.com/pet_home/leaf/log"
|
||||
)
|
||||
|
||||
const (
|
||||
GUIDE_TASK_CONST = "GuideTaskConst"
|
||||
GUIDE_TASK_TASK = "GuideTaskTask"
|
||||
GUIDE_TASK_ACTIVE = "GuideTaskActive"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gamedata.InitCfg(GUIDE_TASK_CONST)
|
||||
gamedata.InitCfg(GUIDE_TASK_TASK)
|
||||
gamedata.InitCfg(GUIDE_TASK_ACTIVE)
|
||||
}
|
||||
|
||||
func GetTaskRewardById(Id int) []*item.Item {
|
||||
data, err := gamedata.GetDataByIntKey(GUIDE_TASK_TASK, Id)
|
||||
if err != nil {
|
||||
log.Debug("GetTaskRewardById err:%v, Id=%d", err, Id)
|
||||
return nil
|
||||
}
|
||||
return gamedata.GetItemList(data, "Items")
|
||||
}
|
||||
|
||||
func GetTaskById(Id int) string {
|
||||
data, err := gamedata.GetDataByIntKey(GUIDE_TASK_TASK, Id)
|
||||
if err != nil {
|
||||
log.Debug("GetTaskById err:%v, Id=%d", err, Id)
|
||||
return ""
|
||||
}
|
||||
return gamedata.GetStringValue(data, "Task")
|
||||
}
|
||||
|
||||
func GetTaskActive(Id int) int {
|
||||
data, err := gamedata.GetDataByIntKey(GUIDE_TASK_TASK, Id)
|
||||
if err != nil {
|
||||
log.Debug("GetTaskActive err:%v, Id=%d", err, Id)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Active")
|
||||
}
|
||||
func GetUnlock(Id int) int {
|
||||
data, err := gamedata.GetDataByIntKey(GUIDE_TASK_TASK, Id)
|
||||
if err != nil {
|
||||
log.Debug("GetUnlock err:%v, Id=%d", err, Id)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Unlock")
|
||||
}
|
||||
|
||||
func GetActiveReward(Id int) ([]*item.Item, int) {
|
||||
data, err := gamedata.GetDataByIntKey(GUIDE_TASK_ACTIVE, Id)
|
||||
if err != nil {
|
||||
log.Debug("GetActiveReward err:%v, Id=%d", err, Id)
|
||||
return nil, 0
|
||||
}
|
||||
return gamedata.GetItemList(data, "Items"), gamedata.GetIntValue(data, "Active")
|
||||
}
|
||||
func GetActiveReward2(reward []int, Active int) []*item.Item {
|
||||
data, err := gamedata.GetData(GUIDE_TASK_ACTIVE)
|
||||
if err != nil {
|
||||
log.Debug("GetActiveReward2 err:%v, Active=%d", err, Active)
|
||||
return nil
|
||||
}
|
||||
for k, v := range data {
|
||||
active := gamedata.GetIntValue(v, "Active")
|
||||
if active < Active {
|
||||
continue
|
||||
}
|
||||
if GoUtil.InArray(GoUtil.Int(k), reward) {
|
||||
continue
|
||||
}
|
||||
return gamedata.GetItemList(v, "Items")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetUnlockLv() int {
|
||||
data, err := gamedata.GetDataByKey(GUIDE_TASK_CONST, "UnlockLv")
|
||||
if err != nil {
|
||||
log.Debug("GetUnlockLv err:%v", err)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
func GetDays() int {
|
||||
data, err := gamedata.GetDataByKey(GUIDE_TASK_CONST, "Days")
|
||||
if err != nil {
|
||||
log.Debug("GetDays err:%v", err)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
func GetTaskList(Lv int) map[int]string {
|
||||
data, err := gamedata.GetData(GUIDE_TASK_TASK)
|
||||
if err != nil {
|
||||
log.Debug("GetTaskList err:%v, Lv=%d", err, Lv)
|
||||
return nil
|
||||
}
|
||||
r := make(map[int]string, len(data))
|
||||
for k, v := range data {
|
||||
k1, err := strconv.Atoi(k)
|
||||
if err != nil {
|
||||
log.Debug("GetTaskList parse id err:%v, key=%s", err, k)
|
||||
continue
|
||||
}
|
||||
r[k1] = gamedata.GetStringValue(v, "Task")
|
||||
}
|
||||
return r
|
||||
}
|
||||
@ -1,24 +0,0 @@
|
||||
package guildCfg
|
||||
|
||||
import (
|
||||
"server/game/mod/item"
|
||||
"server/gamedata"
|
||||
"server/pkg/github.com/name5566/leaf/log"
|
||||
)
|
||||
|
||||
const (
|
||||
GUILD_REWARD = "GuildReward"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gamedata.InitCfg(GUILD_REWARD)
|
||||
}
|
||||
|
||||
func GetGuildReward(Id int) ([]*item.Item, int) {
|
||||
data, err := gamedata.GetDataByIntKey(GUILD_REWARD, Id)
|
||||
if err != nil {
|
||||
log.Debug("GuildCfg GetGuildReward Id:%v not found", Id)
|
||||
return nil, 0
|
||||
}
|
||||
return item.ParseItem(gamedata.GetValue(data, "Items")), gamedata.GetIntValue(data, "Num")
|
||||
}
|
||||
36
src/server/conf/handbook/handbook_cfg.go
Normal file
36
src/server/conf/handbook/handbook_cfg.go
Normal file
@ -0,0 +1,36 @@
|
||||
package handbookCfg
|
||||
|
||||
import (
|
||||
"server/game/mod/item"
|
||||
"server/gamedata"
|
||||
|
||||
"gitea.bywaystudios.com/pet_home/leaf/log"
|
||||
)
|
||||
|
||||
const (
|
||||
CFG_HANDBOOK = "Handbook"
|
||||
CFG_HANDBOOK_CONST = "HandbookConst"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gamedata.InitCfg(CFG_HANDBOOK)
|
||||
gamedata.InitCfg(CFG_HANDBOOK_CONST)
|
||||
}
|
||||
|
||||
func GetHandbookReward(Type string) []*item.Item {
|
||||
data, err := gamedata.GetDataByKey(CFG_HANDBOOK, Type)
|
||||
if err != nil {
|
||||
log.Debug("GetHandbookReward err:%v, Type=%s", err, Type)
|
||||
return nil
|
||||
}
|
||||
return gamedata.GetItemList(data, "Items")
|
||||
}
|
||||
|
||||
func GetHandbookCollectReward() []*item.Item {
|
||||
data, err := gamedata.GetDataByKey(CFG_HANDBOOK_CONST, "collect_item")
|
||||
if err != nil {
|
||||
log.Debug("GetHandbookCollectReward err:%v", err)
|
||||
return nil
|
||||
}
|
||||
return gamedata.GetItemList(data, "Value")
|
||||
}
|
||||
25
src/server/conf/invite/invite_cfg.go
Normal file
25
src/server/conf/invite/invite_cfg.go
Normal file
@ -0,0 +1,25 @@
|
||||
package inviteCfg
|
||||
|
||||
import (
|
||||
"server/game/mod/item"
|
||||
"server/gamedata"
|
||||
|
||||
"gitea.bywaystudios.com/pet_home/leaf/log"
|
||||
)
|
||||
|
||||
const (
|
||||
CFG_INVITE = "Invite"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gamedata.InitCfg(CFG_INVITE)
|
||||
}
|
||||
|
||||
func GetInviteReward(index int) (int, []*item.Item) {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_INVITE, index)
|
||||
if err != nil {
|
||||
log.Debug("GetInviteReward err:%v, index=%d", err, index)
|
||||
return 0, nil
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Need"), gamedata.GetItemList(data, "Items")
|
||||
}
|
||||
@ -1,48 +0,0 @@
|
||||
package itemCfg
|
||||
|
||||
import (
|
||||
"server/gamedata"
|
||||
"server/pkg/github.com/name5566/leaf/log"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var CFG_NAME = "Item"
|
||||
|
||||
func init() {
|
||||
gamedata.InitCfg(CFG_NAME)
|
||||
}
|
||||
|
||||
func GetItemType(Id int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, Id)
|
||||
if err != nil {
|
||||
log.Debug("ItemCfg GetItemType Id:%v not found", Id)
|
||||
return 0
|
||||
}
|
||||
return gamedata.ParseInt(data["IType"])
|
||||
}
|
||||
|
||||
func GetItemEffect(Id int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, Id)
|
||||
if err != nil {
|
||||
log.Debug("ItemCfg GetItemEffect Id:%v not found", Id)
|
||||
return 0
|
||||
}
|
||||
return gamedata.ParseInt(data["Effect"])
|
||||
}
|
||||
|
||||
func GetItemEffectList(Id int) []int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, Id)
|
||||
if err != nil {
|
||||
log.Debug("ItemCfg GetItemEffect Id:%v not found", Id)
|
||||
return []int{}
|
||||
}
|
||||
var res []int
|
||||
str := gamedata.GetStringValue(data, "Effect")
|
||||
a := strings.Split(str, ",")
|
||||
for _, v := range a {
|
||||
b, _ := strconv.Atoi(v)
|
||||
res = append(res, b)
|
||||
}
|
||||
return res
|
||||
}
|
||||
65
src/server/conf/item/Item_cfg.go
Normal file
65
src/server/conf/item/Item_cfg.go
Normal file
@ -0,0 +1,65 @@
|
||||
package itemCfg
|
||||
|
||||
import (
|
||||
languageCfg "server/conf/language"
|
||||
"server/gamedata"
|
||||
"server/msg"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"gitea.bywaystudios.com/pet_home/leaf/log"
|
||||
)
|
||||
|
||||
var CFG_NAME = "Item"
|
||||
|
||||
func init() {
|
||||
gamedata.InitCfg(CFG_NAME)
|
||||
}
|
||||
|
||||
func GetItemType(Id int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, Id)
|
||||
if err != nil {
|
||||
log.Debug("GetItemType err:%v, Id=%d", err, Id)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "IType")
|
||||
}
|
||||
|
||||
func GetItemEffect(Id int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, Id)
|
||||
if err != nil {
|
||||
log.Debug("GetItemEffect err:%v, Id=%d", err, Id)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Effect")
|
||||
}
|
||||
|
||||
func GetItemEffectList(Id int) []int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, Id)
|
||||
if err != nil {
|
||||
log.Debug("GetItemEffectList err:%v, Id=%d", err, Id)
|
||||
return nil
|
||||
}
|
||||
str := gamedata.GetStringValue(data, "Effect")
|
||||
a := strings.Split(str, ",")
|
||||
res := make([]int, 0, len(a))
|
||||
for _, v := range a {
|
||||
b, err := strconv.Atoi(v)
|
||||
if err != nil {
|
||||
log.Debug("GetItemEffectList parse err:%v, v=%s", err, v)
|
||||
continue
|
||||
}
|
||||
res = append(res, b)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func GetItemName(Id int) (string, string) {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, Id)
|
||||
if err != nil {
|
||||
log.Debug("GetItemName err:%v, Id=%d", err, Id)
|
||||
return "", ""
|
||||
}
|
||||
name := gamedata.GetStringValue(data, "Name")
|
||||
return languageCfg.GetLanguage(msg.LANG_TYPE_LANG_CN, name), languageCfg.GetLanguage(msg.LANG_TYPE_LANG_EN, name)
|
||||
}
|
||||
@ -5,13 +5,16 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"server/pkg/github.com/name5566/leaf/log"
|
||||
"gitea.bywaystudios.com/pet_home/leaf/log"
|
||||
)
|
||||
|
||||
var Server struct {
|
||||
AppID int
|
||||
AppPath string
|
||||
LogLevel string
|
||||
LogPath string
|
||||
WSAddr string
|
||||
RPCAddr string
|
||||
CertFile string
|
||||
KeyFile string
|
||||
TCPAddr string
|
||||
@ -28,6 +31,12 @@ var Server struct {
|
||||
RedisAddr string
|
||||
RedisPort string
|
||||
RedisPwd string
|
||||
RedisDb int
|
||||
|
||||
RedisWriteAddr string // 主写地址(host:port 或 单独 host, 仍兼容旧 RedisAddr/RedisPort)
|
||||
RedisReadAddrs string // 只读地址,逗号分隔(host:port,...)
|
||||
RedisMasterName string // 哨兵模式下的 master 名称
|
||||
RedisConnType string // "Direct" 或 "Sentinel"
|
||||
|
||||
GameName string
|
||||
ServerType string
|
||||
@ -39,13 +48,28 @@ var Server struct {
|
||||
|
||||
ListenAddr string
|
||||
CenterAddr string
|
||||
CenterNode int
|
||||
|
||||
RemoteAddr string
|
||||
RemoteAddr string
|
||||
GameConfPath string
|
||||
TELOGDIR string
|
||||
GoogleVerify bool
|
||||
Partition int
|
||||
KafkaHost string
|
||||
KafkaPort string
|
||||
Version string
|
||||
CountryCode string
|
||||
IdVerify bool
|
||||
}
|
||||
|
||||
func init() {
|
||||
// data, err := ioutil.ReadFile("conf/server.json")
|
||||
file, err := os.Open("conf/server.json")
|
||||
filePath := "conf/server.json"
|
||||
if len(os.Args) == 2 {
|
||||
if os.Args[1] != "" && os.Args[1][0] != '-' {
|
||||
filePath = os.Args[1]
|
||||
}
|
||||
}
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
64
src/server/conf/language/language_cfg.go
Normal file
64
src/server/conf/language/language_cfg.go
Normal file
@ -0,0 +1,64 @@
|
||||
package languageCfg
|
||||
|
||||
import (
|
||||
"server/gamedata"
|
||||
"server/msg"
|
||||
)
|
||||
|
||||
const (
|
||||
CFG_LANGUAGE = "LanguageData"
|
||||
CFG_ALLLANGUAGE = "AllLanguage"
|
||||
CFG_ALLLANGUAGE_CLIENT = "AllLanguageClient"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gamedata.InitCfg(CFG_LANGUAGE)
|
||||
gamedata.InitCfg(CFG_ALLLANGUAGE)
|
||||
gamedata.InitCfg(CFG_ALLLANGUAGE_CLIENT)
|
||||
}
|
||||
|
||||
func GetLanguage(lang msg.LANG_TYPE, key string) string {
|
||||
res := _GetClientLanguage(lang, key)
|
||||
if res != key {
|
||||
return res
|
||||
}
|
||||
return _GetBackendLanguage(lang, key)
|
||||
}
|
||||
|
||||
func _GetClientLanguage(lang msg.LANG_TYPE, key string) string {
|
||||
data, err := gamedata.GetDataByKey(CFG_ALLLANGUAGE_CLIENT, key)
|
||||
if err != nil {
|
||||
return key
|
||||
}
|
||||
switch lang {
|
||||
case msg.LANG_TYPE_LANG_EN:
|
||||
return gamedata.GetStringValue(data, "en_US")
|
||||
case msg.LANG_TYPE_LANG_PTBR:
|
||||
return gamedata.GetStringValue(data, "pt_BR")
|
||||
case msg.LANG_TYPE_LANG_CN:
|
||||
return gamedata.GetStringValue(data, "zh_CN")
|
||||
case msg.LANG_TYPE_LANG_ES_LATAM:
|
||||
return gamedata.GetStringValue(data, "es_LATAM")
|
||||
default:
|
||||
return key
|
||||
}
|
||||
}
|
||||
|
||||
func _GetBackendLanguage(lang msg.LANG_TYPE, key string) string {
|
||||
data, err := gamedata.GetDataByKey(CFG_ALLLANGUAGE, key)
|
||||
if err != nil {
|
||||
return key
|
||||
}
|
||||
switch lang {
|
||||
case msg.LANG_TYPE_LANG_EN:
|
||||
return gamedata.GetStringValue(data, "en_US")
|
||||
case msg.LANG_TYPE_LANG_PTBR:
|
||||
return gamedata.GetStringValue(data, "pt_BR")
|
||||
case msg.LANG_TYPE_LANG_CN:
|
||||
return gamedata.GetStringValue(data, "zh_CN")
|
||||
case msg.LANG_TYPE_LANG_ES_LATAM:
|
||||
return gamedata.GetStringValue(data, "es_LATAM")
|
||||
default:
|
||||
return key
|
||||
}
|
||||
}
|
||||
@ -1,219 +0,0 @@
|
||||
package limitedTimeEventCfg
|
||||
|
||||
import (
|
||||
"server/GoUtil"
|
||||
"server/game/mod/item"
|
||||
"server/gamedata"
|
||||
"server/pkg/github.com/name5566/leaf/log"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
CFG_LIMITED_TIME_EVENT = "LimitedTimeEvent"
|
||||
CFG_LIMITED_TIME_EVENT_METEOR = "LimitedTimeEventMeteor"
|
||||
CFG_LIMITED_TIME_EVENT_CHEST = "LimitedTimeEventChest"
|
||||
CFG_LIMITED_TIME_EVENT_ORDER = "LimitedTimeEventOrder"
|
||||
CFG_LIMITED_TIME_EVENT_SENCE = "LimitedTimeEventSence"
|
||||
CFG_LIMITED_TIME_EVENT_SENCE_JACKPOT = "LimitedTimeEventSenceJackpot"
|
||||
CFG_LIMITED_TIME_EVENT_FAST = "LimitedTimeEventFast"
|
||||
CFG_LIMITED_TIME_EVENT_JACKPOT = "LimitedTimeEventJackpot"
|
||||
CFG_LIMITED_TIME_EVENT_CONST = "LimitedTimeEventConst"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gamedata.InitCfg(CFG_LIMITED_TIME_EVENT)
|
||||
gamedata.InitCfg(CFG_LIMITED_TIME_EVENT_METEOR)
|
||||
gamedata.InitCfg(CFG_LIMITED_TIME_EVENT_CHEST)
|
||||
gamedata.InitCfg(CFG_LIMITED_TIME_EVENT_ORDER)
|
||||
gamedata.InitCfg(CFG_LIMITED_TIME_EVENT_SENCE)
|
||||
gamedata.InitCfg(CFG_LIMITED_TIME_EVENT_SENCE_JACKPOT)
|
||||
gamedata.InitCfg(CFG_LIMITED_TIME_EVENT_FAST)
|
||||
gamedata.InitCfg(CFG_LIMITED_TIME_EVENT_JACKPOT)
|
||||
gamedata.InitCfg(CFG_LIMITED_TIME_EVENT_CONST)
|
||||
}
|
||||
|
||||
// 获取限时事件触发列表
|
||||
func GetLimitedTimeEventCfg() []*gamedata.LimitedTimeEventData {
|
||||
data, err := gamedata.GetData(CFG_LIMITED_TIME_EVENT)
|
||||
if err != nil {
|
||||
log.Debug("GetLimitedTimeEventCfg err:%v", err)
|
||||
return nil
|
||||
}
|
||||
var res []*gamedata.LimitedTimeEventData
|
||||
Day, Hour := GoUtil.GetWeekdayAndHour()
|
||||
for k, v := range data {
|
||||
weekDay := gamedata.GetIntValue(v, "WeekDay")
|
||||
startTime := gamedata.GetIntValue(v, "StartTime")
|
||||
endTime := gamedata.GetIntValue(v, "EndTime")
|
||||
if weekDay == Day && Hour >= startTime && Hour < endTime {
|
||||
Id, _ := strconv.Atoi(k)
|
||||
res = append(res, &gamedata.LimitedTimeEventData{
|
||||
Id: Id,
|
||||
EventId: gamedata.GetIntValue(v, "EventId"),
|
||||
Duration: int64(gamedata.GetIntValue(v, "Duration")),
|
||||
})
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// 获取流星雨加成
|
||||
func GetMeteorAdd(ChessLv int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_LIMITED_TIME_EVENT_METEOR, ChessLv)
|
||||
if err != nil {
|
||||
log.Debug("GetMeteorAdd err:%v", err)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Add")
|
||||
}
|
||||
|
||||
// 获取宝箱雨奖励
|
||||
func GetChestReward(Star int) []*item.Item {
|
||||
data, err := gamedata.GetData(CFG_LIMITED_TIME_EVENT_CHEST)
|
||||
if err != nil {
|
||||
log.Debug("GetChestReward err:%v", err)
|
||||
return nil
|
||||
}
|
||||
for _, v := range data {
|
||||
Min := gamedata.GetIntValue(v, "Min")
|
||||
Max := gamedata.GetIntValue(v, "Max")
|
||||
if Star >= Min && Star <= Max {
|
||||
return gamedata.GetItemList(v, "Items")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 获取超级订单奖励
|
||||
func GetSuperOrderReward(Star int) []*item.Item {
|
||||
data, err := gamedata.GetData(CFG_LIMITED_TIME_EVENT_ORDER)
|
||||
if err != nil {
|
||||
log.Debug("GetSuperOrderReward err:%v", err)
|
||||
return nil
|
||||
}
|
||||
for _, v := range data {
|
||||
Min := gamedata.GetIntValue(v, "Min")
|
||||
Max := gamedata.GetIntValue(v, "Max")
|
||||
if Star >= Min && Star <= Max {
|
||||
return gamedata.GetItemList(v, "Items")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 获取场景冲刺奖励
|
||||
func GetSceneDashReward(Sence, Progress int) (int, []*item.Item) {
|
||||
data, err := gamedata.GetData(CFG_LIMITED_TIME_EVENT_SENCE)
|
||||
if err != nil {
|
||||
log.Debug("GetSceneDashReward err:%v", err)
|
||||
return 0, nil
|
||||
}
|
||||
for k, v := range data {
|
||||
if Sence == gamedata.GetIntValue(v, "Sence") && Progress == gamedata.GetIntValue(v, "Progress") {
|
||||
return GoUtil.Int(k), gamedata.GetItemList(v, "Items")
|
||||
}
|
||||
}
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func GetSenceJackpotProb() map[int]int {
|
||||
r := make(map[int]int)
|
||||
data, err := gamedata.GetData(CFG_LIMITED_TIME_EVENT_SENCE_JACKPOT)
|
||||
if err != nil {
|
||||
log.Debug("GetSenceJackpotReward err:%v", err)
|
||||
return nil
|
||||
}
|
||||
for k, v := range data {
|
||||
Id := GoUtil.Int(k)
|
||||
r[Id] = gamedata.GetIntValue(v, "Prob")
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func GetSenceJackpotReward(Id int) []*item.Item {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_LIMITED_TIME_EVENT_SENCE_JACKPOT, Id)
|
||||
if err != nil {
|
||||
log.Debug("GetSenceJackpotReward err:%v", err)
|
||||
return nil
|
||||
}
|
||||
return gamedata.GetItemList(data, "Items")
|
||||
}
|
||||
|
||||
// 获取连击快手奖励
|
||||
func GetFastProduceReward(Times, Energy int) []*item.Item {
|
||||
data, err := gamedata.GetData(CFG_LIMITED_TIME_EVENT_FAST)
|
||||
if err != nil {
|
||||
log.Debug("GetSceneDashReward err:%v", err)
|
||||
return nil
|
||||
}
|
||||
for _, v := range data {
|
||||
if Times == gamedata.GetIntValue(v, "Times") && Energy <= gamedata.GetIntValue(v, "Max") && Energy >= gamedata.GetIntValue(v, "Min") {
|
||||
return gamedata.GetItemList(v, "Items")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetProgressMax() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_LIMITED_TIME_EVENT_CONST, "Progress_max")
|
||||
if err != nil {
|
||||
log.Debug("GetProgressMax err:%v", err)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "value")
|
||||
}
|
||||
|
||||
func GetProgressRewardRand(Lv int) map[int]int {
|
||||
data, err := gamedata.GetData(CFG_LIMITED_TIME_EVENT_JACKPOT)
|
||||
if err != nil {
|
||||
log.Debug("GetProgressRewardRand err:%v", err)
|
||||
return nil
|
||||
}
|
||||
r := make(map[int]int)
|
||||
for k, v := range data {
|
||||
if Lv >= gamedata.GetIntValue(v, "Min") && Lv <= gamedata.GetIntValue(v, "Max") {
|
||||
Id := GoUtil.Int(k)
|
||||
r[Id] = gamedata.GetIntValue(v, "Prob")
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func GetProgressSelectNum(Lv int) int {
|
||||
data, err := gamedata.GetDataByKey(CFG_LIMITED_TIME_EVENT_CONST, "Progress_lv_num")
|
||||
if err != nil {
|
||||
log.Debug("GetProgressSelectNum err:%v", err)
|
||||
return 0
|
||||
}
|
||||
Str := gamedata.GetStringValue(data, "value")
|
||||
Strarr := strings.Split(Str, ";")
|
||||
for _, v := range Strarr {
|
||||
a := strings.Split(v, ",")
|
||||
if len(a) != 3 {
|
||||
continue
|
||||
}
|
||||
Min, _ := strconv.Atoi(a[0])
|
||||
Max, _ := strconv.Atoi(a[1])
|
||||
if Lv >= Min && Lv <= Max {
|
||||
Num, _ := strconv.Atoi(a[2])
|
||||
return Num
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func GetProgressReward(RewardId int) []*item.Item {
|
||||
data, err := gamedata.GetData(CFG_LIMITED_TIME_EVENT_JACKPOT)
|
||||
if err != nil {
|
||||
log.Debug("GetProgressReward err:%v", err)
|
||||
return nil
|
||||
}
|
||||
for k, v := range data {
|
||||
Id := GoUtil.Int(k)
|
||||
if Id == RewardId {
|
||||
return gamedata.GetItemList(v, "Items")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
457
src/server/conf/limited_time_event/limited_time_event_cfg.go
Normal file
457
src/server/conf/limited_time_event/limited_time_event_cfg.go
Normal file
@ -0,0 +1,457 @@
|
||||
package limitedTimeEventCfg
|
||||
|
||||
import (
|
||||
"math"
|
||||
"server/game/mod/item"
|
||||
GoUtil "server/game_util"
|
||||
"server/gamedata"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"gitea.bywaystudios.com/pet_home/leaf/log"
|
||||
)
|
||||
|
||||
const (
|
||||
CFG_LIMITED_TIME_EVENT = "LimitedTimeEvent"
|
||||
CFG_LIMITED_TIME_EVENT_METEOR = "LimitedTimeEventMeteor"
|
||||
CFG_LIMITED_TIME_EVENT_CHEST = "LimitedTimeEventChest"
|
||||
CFG_LIMITED_TIME_EVENT_ORDER = "LimitedTimeEventOrder"
|
||||
CFG_LIMITED_TIME_EVENT_SENCE = "LimitedTimeEventSence"
|
||||
CFG_LIMITED_TIME_EVENT_SENCE_JACKPOT = "LimitedTimeEventSenceJackpot"
|
||||
CFG_LIMITED_TIME_EVENT_FAST = "LimitedTimeEventFast"
|
||||
CFG_LIMITED_TIME_EVENT_JACKPOT = "LimitedTimeEventJackpot"
|
||||
CFG_LIMITED_TIME_EVENT_CHEST_JACKPOT = "LimitedTimeEventChestJackpot"
|
||||
CFG_LIMITED_TIME_EVENT_CONST = "LimitedTimeEventConst"
|
||||
CFG_LIMITED_TIME_EVENT_BONUS = "LimitedTimeEventBonus"
|
||||
CFG_LIMITED_TIME_EVENT_MONEY = "LimitedTimeEventMoney"
|
||||
CFG_LIMITED_TIME_EVENT_LUCKY = "LimitedTimeEventLucky"
|
||||
CFG_LIMTTED_TIME_EVENT_DECORATE_OFF = "LimitedTimeEventDecorateOff"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gamedata.InitCfg(CFG_LIMITED_TIME_EVENT)
|
||||
gamedata.InitCfg(CFG_LIMITED_TIME_EVENT_METEOR)
|
||||
gamedata.InitCfg(CFG_LIMITED_TIME_EVENT_CHEST)
|
||||
gamedata.InitCfg(CFG_LIMITED_TIME_EVENT_ORDER)
|
||||
gamedata.InitCfg(CFG_LIMITED_TIME_EVENT_SENCE)
|
||||
gamedata.InitCfg(CFG_LIMITED_TIME_EVENT_SENCE_JACKPOT)
|
||||
gamedata.InitCfg(CFG_LIMITED_TIME_EVENT_FAST)
|
||||
gamedata.InitCfg(CFG_LIMITED_TIME_EVENT_JACKPOT)
|
||||
gamedata.InitCfg(CFG_LIMITED_TIME_EVENT_CONST)
|
||||
gamedata.InitCfg(CFG_LIMITED_TIME_EVENT_BONUS)
|
||||
gamedata.InitCfg(CFG_LIMITED_TIME_EVENT_CHEST_JACKPOT)
|
||||
gamedata.InitCfg(CFG_LIMITED_TIME_EVENT_MONEY)
|
||||
gamedata.InitCfg(CFG_LIMITED_TIME_EVENT_LUCKY)
|
||||
gamedata.InitCfg(CFG_LIMTTED_TIME_EVENT_DECORATE_OFF)
|
||||
}
|
||||
|
||||
// 获取限时事件触发列表
|
||||
func GetLimitedTimeEventCfg() []*gamedata.LimitedTimeEventData {
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetEventName(Id int) string {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_LIMITED_TIME_EVENT, Id)
|
||||
if err != nil {
|
||||
log.Debug("GetEventName err:%v, Id=%d", err, Id)
|
||||
return ""
|
||||
}
|
||||
return gamedata.GetStringValue(data, "Name")
|
||||
}
|
||||
|
||||
// 获取流星雨加成
|
||||
func GetMeteorAdd(ChessLv int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_LIMITED_TIME_EVENT_METEOR, ChessLv)
|
||||
if err != nil {
|
||||
log.Debug("GetMeteorAdd err:%v, ChessLv=%d", err, ChessLv)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Add")
|
||||
}
|
||||
|
||||
// 获取宝箱雨奖励
|
||||
func GetChestReward(Star int) []*item.Item {
|
||||
data, err := gamedata.GetData(CFG_LIMITED_TIME_EVENT_CHEST)
|
||||
if err != nil {
|
||||
log.Debug("GetChestReward err:%v, Star=%d", err, Star)
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, v := range data {
|
||||
Min := gamedata.GetIntValue(v, "Min")
|
||||
Max := gamedata.GetIntValue(v, "Max")
|
||||
if Star >= Min && Star <= Max {
|
||||
return gamedata.GetItemList(v, "Items")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
// 获取超级订单奖励
|
||||
func GetSuperOrderReward(energy int) []*item.Item {
|
||||
data, err := gamedata.GetData(CFG_LIMITED_TIME_EVENT_ORDER)
|
||||
if err != nil {
|
||||
log.Debug("GetSuperOrderReward err:%v, energy=%d", err, energy)
|
||||
return nil
|
||||
}
|
||||
star := energy
|
||||
for _, v := range data {
|
||||
Min := gamedata.GetIntValue(v, "Min")
|
||||
Max := gamedata.GetIntValue(v, "Max")
|
||||
if star >= Min && star <= Max {
|
||||
return gamedata.GetItemList(v, "Items")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 获取场景冲刺奖励
|
||||
func GetSceneDashReward(Sence, Progress int) (int, []*item.Item) {
|
||||
data, err := gamedata.GetData(CFG_LIMITED_TIME_EVENT_SENCE)
|
||||
if err != nil {
|
||||
log.Debug("GetSceneDashReward err:%v, Sence=%d, Progress=%d", err, Sence, Progress)
|
||||
return 0, nil
|
||||
}
|
||||
for k, v := range data {
|
||||
if Sence == gamedata.GetIntValue(v, "Sence") && Progress == gamedata.GetIntValue(v, "Progress") {
|
||||
return GoUtil.Int(k), gamedata.GetItemList(v, "Items")
|
||||
}
|
||||
}
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// 获取场景冲刺奖池
|
||||
func GetSenceJackpotProb() map[int]int {
|
||||
data, err := gamedata.GetData(CFG_LIMITED_TIME_EVENT_SENCE_JACKPOT)
|
||||
if err != nil {
|
||||
log.Debug("GetSenceJackpotProb err:%v", err)
|
||||
return nil
|
||||
}
|
||||
r := make(map[int]int, len(data))
|
||||
for k, v := range data {
|
||||
Id := GoUtil.Int(k)
|
||||
r[Id] = gamedata.GetIntValue(v, "Prob")
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// 获取场景冲刺奖励
|
||||
func GetSenceJackpotReward(Id int) []*item.Item {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_LIMITED_TIME_EVENT_SENCE_JACKPOT, Id)
|
||||
if err != nil {
|
||||
log.Debug("GetSenceJackpotReward err:%v, Id=%d", err, Id)
|
||||
return nil
|
||||
}
|
||||
return gamedata.GetItemList(data, "Items")
|
||||
}
|
||||
|
||||
// 获取连击快手奖励
|
||||
func GetFastProduceReward(Energy int) []*item.Item {
|
||||
data, err := gamedata.GetData(CFG_LIMITED_TIME_EVENT_FAST)
|
||||
if err != nil {
|
||||
log.Debug("GetFastProduceReward err:%v, Energy=%d", err, Energy)
|
||||
return nil
|
||||
}
|
||||
if len(data) == 0 {
|
||||
return nil
|
||||
}
|
||||
// Convert map to slice for sorting
|
||||
type sortData struct {
|
||||
Id string
|
||||
Energy float64
|
||||
}
|
||||
sortedList := make([]sortData, 0, len(data))
|
||||
energy := float64(Energy) / 10.0
|
||||
for k, v := range data {
|
||||
dataEnergy := gamedata.GetFloatValue(v, "EnergyValue")
|
||||
sortedList = append(sortedList, sortData{k, math.Abs(energy - dataEnergy)})
|
||||
}
|
||||
// Sort by Energy in ascending order
|
||||
sort.Slice(sortedList, func(i, j int) bool {
|
||||
return sortedList[i].Energy < sortedList[j].Energy
|
||||
})
|
||||
|
||||
return gamedata.GetItemList(data[sortedList[0].Id], "Items")
|
||||
}
|
||||
|
||||
// 获取连击快手最大次数
|
||||
func GetFastProduceMaxTimes() int {
|
||||
Max := 0
|
||||
data, err := gamedata.GetData(CFG_LIMITED_TIME_EVENT_FAST)
|
||||
if err != nil {
|
||||
log.Debug("GetFastProduceMaxTimes err:%v", err)
|
||||
return 0
|
||||
}
|
||||
for _, v := range data {
|
||||
Max = max(gamedata.GetIntValue(v, "Times"), Max)
|
||||
}
|
||||
return Max
|
||||
}
|
||||
|
||||
// 获取进度最大值
|
||||
func GetProgressMax(Lv, Num int) int {
|
||||
data, err := gamedata.GetData(CFG_LIMITED_TIME_EVENT_BONUS)
|
||||
if err != nil {
|
||||
log.Debug("GetProgressMax err:%v, Lv=%d, Num=%d", err, Lv, Num)
|
||||
return 0
|
||||
}
|
||||
for _, v := range data {
|
||||
Min := gamedata.GetIntValue(v, "Min")
|
||||
Max := gamedata.GetIntValue(v, "Max")
|
||||
if Lv >= Min && Lv <= Max {
|
||||
OrderNumStr := gamedata.GetStringValue(v, "OrderNum")
|
||||
OrderNum := GoUtil.SplitInt(OrderNumStr, ",")
|
||||
if Num >= len(OrderNum) {
|
||||
return OrderNum[len(OrderNum)-1]
|
||||
} else {
|
||||
return OrderNum[Num]
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func GetBonusLv(Lv int) int {
|
||||
data, err := gamedata.GetData(CFG_LIMITED_TIME_EVENT_BONUS)
|
||||
if err != nil {
|
||||
log.Debug("GetBonusLv err:%v, Lv=%d", err, Lv)
|
||||
return 0
|
||||
}
|
||||
for k, v := range data {
|
||||
Min := gamedata.GetIntValue(v, "Min")
|
||||
Max := gamedata.GetIntValue(v, "Max")
|
||||
if Lv >= Min && Lv <= Max {
|
||||
return GoUtil.Int(k)
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// 获取进度奖励随机
|
||||
func GetProgressRewardRand(Lv int) map[int]int {
|
||||
data, err := gamedata.GetData(CFG_LIMITED_TIME_EVENT_JACKPOT)
|
||||
if err != nil {
|
||||
log.Debug("GetProgressRewardRand err:%v, Lv=%d", err, Lv)
|
||||
return nil
|
||||
}
|
||||
r := make(map[int]int, len(data))
|
||||
for k, v := range data {
|
||||
if Lv >= gamedata.GetIntValue(v, "BonusLv") {
|
||||
Id := GoUtil.Int(k)
|
||||
r[Id] = gamedata.GetIntValue(v, "Prob")
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func GetJackpotIdByType(Type int) int {
|
||||
data, err := gamedata.GetData(CFG_LIMITED_TIME_EVENT_JACKPOT)
|
||||
if err != nil {
|
||||
log.Debug("GetJackpotIdByType err:%v, Type=%d", err, Type)
|
||||
return 0
|
||||
}
|
||||
for k, v := range data {
|
||||
Id := GoUtil.Int(k)
|
||||
if Type == gamedata.GetIntValue(v, "Type") {
|
||||
return Id
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// 获取进度选择数量
|
||||
func GetProgressSelectNum(Lv int) int {
|
||||
data, err := gamedata.GetData(CFG_LIMITED_TIME_EVENT_BONUS)
|
||||
if err != nil {
|
||||
log.Debug("GetProgressSelectNum err:%v, Lv=%d", err, Lv)
|
||||
return 0
|
||||
}
|
||||
for _, v := range data {
|
||||
Min := gamedata.GetIntValue(v, "Min")
|
||||
Max := gamedata.GetIntValue(v, "Max")
|
||||
if Lv >= Min && Lv <= Max {
|
||||
return gamedata.GetIntValue(v, "Option")
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// 获取进度奖励
|
||||
func GetProgressReward(RewardId int) []*item.Item {
|
||||
data, err := gamedata.GetData(CFG_LIMITED_TIME_EVENT_JACKPOT)
|
||||
if err != nil {
|
||||
log.Debug("GetProgressReward err:%v, RewardId=%d", err, RewardId)
|
||||
return nil
|
||||
}
|
||||
for k, v := range data {
|
||||
Id := GoUtil.Int(k)
|
||||
if Id == RewardId {
|
||||
return gamedata.GetItemList(v, "Items")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 获取进度奖励类型
|
||||
func GetProgressRewardType(RewardId int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_LIMITED_TIME_EVENT_JACKPOT, RewardId)
|
||||
if err != nil {
|
||||
log.Debug("GetProgressRewardType err:%v, RewardId=%d", err, RewardId)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Type")
|
||||
}
|
||||
|
||||
func GetUnlockLv() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_LIMITED_TIME_EVENT_CONST, "unlock_lv")
|
||||
if err != nil {
|
||||
log.Debug("GetUnlockLv err:%v", err)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
func GetCatSaleCD() int64 {
|
||||
data, err := gamedata.GetDataByKey(CFG_LIMITED_TIME_EVENT_CONST, "Event_Cooldown_7days")
|
||||
if err != nil {
|
||||
log.Debug("GetCatSaleCD err:%v", err)
|
||||
return 0
|
||||
}
|
||||
return int64(gamedata.GetIntValue(data, "Value"))
|
||||
}
|
||||
|
||||
func GetFirstEvent() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_LIMITED_TIME_EVENT_CONST, "First_Event")
|
||||
if err != nil {
|
||||
log.Debug("GetFirstEvent err:%v", err)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
func GetFastCD() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_LIMITED_TIME_EVENT_CONST, "Fast_Cd")
|
||||
if err != nil {
|
||||
log.Debug("GetFastCD err:%v", err)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
func GetPaybackDay() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_LIMITED_TIME_EVENT_CONST, "payback_day")
|
||||
if err != nil {
|
||||
log.Debug("GetPaybackDay err:%v", err)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
func GetHighRollerNeedEnergy() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_LIMITED_TIME_EVENT_CONST, "High_Roller_Need_Energy")
|
||||
if err != nil {
|
||||
log.Debug("GetHighRollerNeedEnergy err:%v", err)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
func GetThiefProb() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_LIMITED_TIME_EVENT_CONST, "Thief_Prob")
|
||||
if err != nil {
|
||||
log.Debug("GetThiefProb err:%v", err)
|
||||
return 0
|
||||
}
|
||||
value := gamedata.GetStringValue(data, "Value")
|
||||
a1 := strings.Split(value, "|")
|
||||
prob := make(map[int]int, len(a1))
|
||||
for _, v := range a1 {
|
||||
a2 := strings.Split(v, ":")
|
||||
prob[GoUtil.Int(a2[0])] = GoUtil.Int(a2[1])
|
||||
}
|
||||
return GoUtil.RandMap(prob)
|
||||
}
|
||||
|
||||
// 招财猫
|
||||
|
||||
func GetMoneyCat(Id int) (float64, int) {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_LIMITED_TIME_EVENT_MONEY, Id)
|
||||
if err != nil {
|
||||
log.Debug("GetMoneyCat err:%v, Id=%d", err, Id)
|
||||
return 0.0, 0
|
||||
}
|
||||
return gamedata.GetFloatValue(data, "Mul"), gamedata.GetIntValue(data, "Cd")
|
||||
}
|
||||
|
||||
func GetMoneyCatMax() int {
|
||||
data, err := gamedata.GetData(CFG_LIMITED_TIME_EVENT_MONEY)
|
||||
if err != nil {
|
||||
log.Debug("GetMoneyCatMax err:%v", err)
|
||||
return 0
|
||||
}
|
||||
return len(data)
|
||||
}
|
||||
|
||||
func GetLuckyCatMaxEarning(Remain int) int {
|
||||
data, err := gamedata.GetData(CFG_LIMITED_TIME_EVENT_LUCKY)
|
||||
if err != nil {
|
||||
log.Debug("GetLuckyCatMaxEarning err:%v, Remain=%d", err, Remain)
|
||||
return 0
|
||||
}
|
||||
type d struct {
|
||||
t int
|
||||
e int
|
||||
}
|
||||
l := make([]d, 0, len(data))
|
||||
for k, v := range data {
|
||||
t := GoUtil.Int(k)
|
||||
e := gamedata.GetIntValue(v, "Earn")
|
||||
l = append(l, d{t, e})
|
||||
}
|
||||
sort.Slice(l, func(i, j int) bool {
|
||||
return l[i].t < l[j].t
|
||||
})
|
||||
for _, v := range l {
|
||||
if Remain <= v.t {
|
||||
return v.e
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func GetCatTrickEnergy() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_LIMITED_TIME_EVENT_CONST, "CatTrick_ConsumeEnergy")
|
||||
if err != nil {
|
||||
log.Debug("GetCatTrickEnergy err:%v", err)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
func GetCatTrickDiamond() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_LIMITED_TIME_EVENT_CONST, "CatTrick_RewardDiamond")
|
||||
if err != nil {
|
||||
log.Debug("GetCatTrickDiamond err:%v", err)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
func GetDecorateOffDiscount(AreaId, StepId int) int {
|
||||
data, err := gamedata.GetData(CFG_LIMTTED_TIME_EVENT_DECORATE_OFF)
|
||||
if err != nil {
|
||||
log.Debug("GetDecorateOffDiscount err:%v, AreaId=%d, StepId=%d", err, AreaId, StepId)
|
||||
return 100
|
||||
}
|
||||
for _, v := range data {
|
||||
StartAreaId := gamedata.GetIntValue(v, "StartArea")
|
||||
EndAreaId := gamedata.GetIntValue(v, "EndArea")
|
||||
StartStepId := gamedata.GetIntValue(v, "StartStep")
|
||||
EndStepId := gamedata.GetIntValue(v, "EndStep")
|
||||
if AreaId >= StartAreaId && AreaId <= EndAreaId && StepId >= StartStepId && StepId <= EndStepId {
|
||||
return gamedata.GetIntValue(v, "Off")
|
||||
}
|
||||
}
|
||||
return 100
|
||||
}
|
||||
112
src/server/conf/mail/mail_cfg.go
Normal file
112
src/server/conf/mail/mail_cfg.go
Normal file
@ -0,0 +1,112 @@
|
||||
package mailCfg
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
languageCfg "server/conf/language"
|
||||
"server/game/mod/item"
|
||||
GoUtil "server/game_util"
|
||||
"server/gamedata"
|
||||
"server/msg"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
CFG_LOGIN_BACK = "LoginBack"
|
||||
CFG_MAIL = "Mail"
|
||||
|
||||
MAIL_RECALL_ID = 12
|
||||
MAIL_CHARGE_SEND_ID = 13
|
||||
MAIL_CHARGE_RECEIVE_ID = 14
|
||||
)
|
||||
|
||||
type TriggerMail struct {
|
||||
Id int
|
||||
Title string
|
||||
SubTitle string
|
||||
Content string
|
||||
EnglistTitle string
|
||||
SubTitleEn string
|
||||
EnglistContent string
|
||||
Items []*item.Item
|
||||
Type int
|
||||
Trigger []string
|
||||
}
|
||||
|
||||
func init() {
|
||||
gamedata.InitCfg(CFG_LOGIN_BACK)
|
||||
gamedata.InitCfg(CFG_MAIL)
|
||||
}
|
||||
|
||||
func GetLoginBack(Id string) (int, int) {
|
||||
data, err := gamedata.GetDataByKey(CFG_LOGIN_BACK, Id)
|
||||
if err != nil {
|
||||
return 0, 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Num1"), gamedata.GetIntValue(data, "Num2")
|
||||
}
|
||||
|
||||
func GetTriggerMail() []*TriggerMail {
|
||||
data, err := gamedata.GetData(CFG_MAIL)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
ret := make([]*TriggerMail, 0)
|
||||
for k, v := range data {
|
||||
T := gamedata.GetStringValue(v, "Trigger")
|
||||
if T == "" {
|
||||
continue
|
||||
}
|
||||
T1 := strings.Split(T, "|")
|
||||
if len(T1) < 4 {
|
||||
continue
|
||||
}
|
||||
data := &TriggerMail{
|
||||
Id: GoUtil.Int(k),
|
||||
Title: gamedata.GetStringValue(v, "Title"),
|
||||
Content: gamedata.GetStringValue(v, "Content"),
|
||||
EnglistTitle: gamedata.GetStringValue(v, "EnglistTitle"),
|
||||
EnglistContent: gamedata.GetStringValue(v, "EnglistContent"),
|
||||
Items: gamedata.GetItemList(v, "Items"),
|
||||
Type: gamedata.GetIntValue(v, "Type"),
|
||||
Trigger: strings.Split(T, "|"),
|
||||
}
|
||||
ret = append(ret, data)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func GetRecallMail(Title, ItemName, TitleEn, ItemNameEn string) (string, string, string, string) {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_MAIL, 12)
|
||||
if err != nil {
|
||||
return "", "", "", ""
|
||||
}
|
||||
mt := languageCfg.GetLanguage(msg.LANG_TYPE_LANG_CN, gamedata.GetStringValue(data, "Title"))
|
||||
mc := languageCfg.GetLanguage(msg.LANG_TYPE_LANG_CN, gamedata.GetStringValue(data, "Content"))
|
||||
mt_en := languageCfg.GetLanguage(msg.LANG_TYPE_LANG_EN, gamedata.GetStringValue(data, "Title"))
|
||||
mc_en := languageCfg.GetLanguage(msg.LANG_TYPE_LANG_EN, gamedata.GetStringValue(data, "Content"))
|
||||
return fmt.Sprintf(mt, Title), fmt.Sprintf(mc, Title, ItemName), fmt.Sprintf(mt_en, TitleEn), fmt.Sprintf(mc_en, Title, ItemNameEn)
|
||||
}
|
||||
|
||||
func GetChargeSendMail(PlayerName string) (string, string, string, string) {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_MAIL, MAIL_CHARGE_SEND_ID)
|
||||
if err != nil {
|
||||
return "", "", "", ""
|
||||
}
|
||||
mt := languageCfg.GetLanguage(msg.LANG_TYPE_LANG_CN, gamedata.GetStringValue(data, "Title"))
|
||||
mc := languageCfg.GetLanguage(msg.LANG_TYPE_LANG_CN, gamedata.GetStringValue(data, "Content"))
|
||||
mt_en := languageCfg.GetLanguage(msg.LANG_TYPE_LANG_EN, gamedata.GetStringValue(data, "Title"))
|
||||
mc_en := languageCfg.GetLanguage(msg.LANG_TYPE_LANG_EN, gamedata.GetStringValue(data, "Content"))
|
||||
return mt, fmt.Sprintf(mc, PlayerName), mt_en, fmt.Sprintf(mc_en, PlayerName)
|
||||
}
|
||||
|
||||
func GetChargeReceiveMail(PlayerName string, Content string) (string, string, string, string) {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_MAIL, MAIL_CHARGE_RECEIVE_ID)
|
||||
if err != nil {
|
||||
return "", "", "", ""
|
||||
}
|
||||
mt := languageCfg.GetLanguage(msg.LANG_TYPE_LANG_CN, gamedata.GetStringValue(data, "Title"))
|
||||
mc := languageCfg.GetLanguage(msg.LANG_TYPE_LANG_CN, gamedata.GetStringValue(data, "Content"))
|
||||
mt_en := languageCfg.GetLanguage(msg.LANG_TYPE_LANG_EN, gamedata.GetStringValue(data, "Title"))
|
||||
mc_en := languageCfg.GetLanguage(msg.LANG_TYPE_LANG_EN, gamedata.GetStringValue(data, "Content"))
|
||||
return fmt.Sprintf(mt, PlayerName), fmt.Sprintf(mc, Content), fmt.Sprintf(mt_en, PlayerName), fmt.Sprintf(mc_en, Content)
|
||||
}
|
||||
@ -1,188 +0,0 @@
|
||||
package mergeDataCfg
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"server/gamedata"
|
||||
"server/pkg/github.com/name5566/leaf/log"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
CFG_NAME = "MergeData"
|
||||
CONST_NAME = "MergeDataConst"
|
||||
|
||||
// 棋子类型
|
||||
CHESS_PRODUCT_MAIN_TYPE = 1 // 主产物
|
||||
CHESS_PRODUCT_SUB_TYPE = 2 // 次产物
|
||||
CHESS_PRODUCT_SUB_EMIT_TYPE = 3 // 次发射器产物
|
||||
)
|
||||
|
||||
func init() {
|
||||
gamedata.InitCfg(CFG_NAME)
|
||||
gamedata.InitCfg(CONST_NAME)
|
||||
}
|
||||
|
||||
// 获取单个数据
|
||||
func GetOne(Id int) (*gamedata.MergeDataRecord, error) {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, Id)
|
||||
if err != nil {
|
||||
log.Debug("MergeDataCfg GetOne Id:%v not found", Id)
|
||||
return &gamedata.MergeDataRecord{}, errors.New("not found")
|
||||
}
|
||||
return &gamedata.MergeDataRecord{
|
||||
Id: gamedata.ParseInt(data["Id"]),
|
||||
Lv: gamedata.ParseInt(data["Lv"]),
|
||||
MaxLv: gamedata.ParseInt(data["MaxLv"]),
|
||||
SellType: gamedata.ParseString(data["SellType"]),
|
||||
SellNum: gamedata.ParseInt(data["SellNum"]),
|
||||
SellDiamond: gamedata.ParseInt(data["SellDiamond"]),
|
||||
Color: gamedata.ParseString(data["Color"]),
|
||||
Star: gamedata.ParseInt(data["Star"]),
|
||||
Type: gamedata.ParseString(data["Type"]),
|
||||
Emit_Product: gamedata.ParseString(data["Emit_Product"]),
|
||||
CoolTime: gamedata.ParseInt(data["CoolTime"]),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 根据id获取棋子获得的星星
|
||||
func GetStarById(Id int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, Id)
|
||||
if err != nil {
|
||||
log.Debug("MergeDataCfg GetOne Id:%v not found", Id)
|
||||
return 0
|
||||
}
|
||||
return gamedata.ParseInt(data["Star"])
|
||||
}
|
||||
|
||||
// 根据等级和颜色获取棋子id
|
||||
func GetChessIdByLvAndColor(Lv int, Color string) int {
|
||||
if Lv == 0 || Color == "" {
|
||||
return 0
|
||||
}
|
||||
data, err := gamedata.GetData(CFG_NAME)
|
||||
if err != nil {
|
||||
log.Debug("MergeDataCfg GetChessIdByLvAndColor lv:%v Color:%v not found", Lv, Color)
|
||||
return 0
|
||||
}
|
||||
for k, v := range data {
|
||||
lv := gamedata.GetIntValue(v, "Lv")
|
||||
color := gamedata.GetStringValue(v, "Color")
|
||||
if Lv == lv && color == Color {
|
||||
Id, _ := strconv.Atoi(k)
|
||||
return Id
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// 根据Id获取棋子等级
|
||||
func GetLvById(Id int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, Id)
|
||||
if err != nil {
|
||||
log.Debug("GetLvById GetOne Id:%v not found", Id)
|
||||
return 0
|
||||
}
|
||||
return gamedata.ParseInt(data["Lv"])
|
||||
}
|
||||
|
||||
// 根据Id获取棋子最大等级
|
||||
func GetMaxLvById(Id int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, Id)
|
||||
if err != nil {
|
||||
log.Debug("GetMaxLvById GetOne Id:%v not found", Id)
|
||||
return 0
|
||||
}
|
||||
return gamedata.ParseInt(data["MaxLv"])
|
||||
}
|
||||
|
||||
// 根据Id获取棋子类型
|
||||
func GetTypeById(Id int) string {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, Id)
|
||||
if err != nil {
|
||||
log.Debug("GetTypeById GetOne Id:%v not found", Id)
|
||||
return ""
|
||||
}
|
||||
return gamedata.ParseString(data["Type"])
|
||||
}
|
||||
|
||||
// 根据Id获取棋子类型
|
||||
func GetColorById(Id int) string {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, Id)
|
||||
if err != nil {
|
||||
log.Debug("GetColorById GetOne Id:%v not found", Id)
|
||||
return ""
|
||||
}
|
||||
return gamedata.ParseString(data["Color"])
|
||||
}
|
||||
|
||||
// 根据Id获取发射器产出类型
|
||||
func GetEmitProduceType(Id int) []string {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, Id)
|
||||
if err != nil {
|
||||
log.Debug("GetTypeById GetOne Id:%v not found", Id)
|
||||
return []string{}
|
||||
}
|
||||
return strings.Split(gamedata.ParseString(data["Emit_Product"]), ",")
|
||||
}
|
||||
|
||||
// 根据Id获取发射器Id
|
||||
func GetEmitId(Id int) string {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, Id)
|
||||
if err != nil {
|
||||
log.Debug("GetTypeById GetOne Id:%v not found", Id)
|
||||
return ""
|
||||
}
|
||||
return gamedata.ParseString(data["Emit_ID"])
|
||||
}
|
||||
|
||||
// 获取常量
|
||||
func GetConst(Key string) string {
|
||||
data, err := gamedata.GetDataByKey(CONST_NAME, Key)
|
||||
if err != nil {
|
||||
log.Debug("GetConst GetOne Id:%s not found", Key)
|
||||
return ""
|
||||
}
|
||||
return gamedata.ParseString(data["Value"])
|
||||
}
|
||||
|
||||
// 获取常量
|
||||
func GetConstInt(Key string) int {
|
||||
data, err := gamedata.GetDataByKey(CONST_NAME, Key)
|
||||
if err != nil {
|
||||
log.Debug("GetConst GetOne Id:%s not found", Key)
|
||||
return 0
|
||||
}
|
||||
return gamedata.ParseInt(data["Value"])
|
||||
}
|
||||
|
||||
func GetExtraEmitId() map[string]struct{} {
|
||||
Value := GetConst("EmitId_Extra_Order")
|
||||
arr := strings.Split(Value, ",")
|
||||
var r = make(map[string]struct{})
|
||||
for _, v := range arr {
|
||||
r[v] = struct{}{}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func GetProductType(Chess int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, Chess)
|
||||
if err != nil {
|
||||
log.Debug("GetProductType GetOne Id:%v not found", Chess)
|
||||
return 0
|
||||
}
|
||||
return gamedata.ParseInt(data["PType"])
|
||||
}
|
||||
|
||||
func GetChessBagMaxGrid() int {
|
||||
return GetConstInt("chess_bag_max")
|
||||
}
|
||||
|
||||
func GetChessBagBugNum() int {
|
||||
return GetConstInt("chess_bag_buy")
|
||||
}
|
||||
|
||||
func GetChessBagInitNum() int {
|
||||
return GetConstInt("chess_bag_init")
|
||||
}
|
||||
620
src/server/conf/merge_data/merge_data_cfg.go
Normal file
620
src/server/conf/merge_data/merge_data_cfg.go
Normal file
@ -0,0 +1,620 @@
|
||||
package mergeDataCfg
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"server/game/mod/item"
|
||||
GoUtil "server/game_util"
|
||||
"server/gamedata"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"gitea.bywaystudios.com/pet_home/leaf/log"
|
||||
)
|
||||
|
||||
const (
|
||||
CFG_NAME = "MergeData"
|
||||
CONST_NAME = "MergeDataConst"
|
||||
CFG_MERGE_EMIT = "MergeDataEmit"
|
||||
|
||||
// 棋子类型
|
||||
CHESS_PRODUCT_MAIN_TYPE = 1 // 主产物
|
||||
CHESS_PRODUCT_SECONDARY_TYPE = 2 // 次产物
|
||||
CHESS_PRODUCT_SUB_TYPE = 3 // 子发射器产物
|
||||
)
|
||||
|
||||
func init() {
|
||||
gamedata.InitCfg(CFG_NAME)
|
||||
gamedata.InitCfg(CONST_NAME)
|
||||
gamedata.InitCfg(CFG_MERGE_EMIT)
|
||||
}
|
||||
|
||||
func GetEmitTypeByColor(Color string) string {
|
||||
data, err := gamedata.GetData(CFG_MERGE_EMIT)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
for k, v := range data {
|
||||
ColorList := strings.Split(gamedata.GetStringValue(v, "Order_Type"), ",")
|
||||
if GoUtil.InStringArray(Color, ColorList) {
|
||||
return k
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func GetEmitProduce(EmitType string) []string {
|
||||
data, err := gamedata.GetDataByKey(CFG_MERGE_EMIT, EmitType)
|
||||
if err != nil {
|
||||
log.Debug("GetEmitProduce GetOne EmitType:%s not found", EmitType)
|
||||
return []string{}
|
||||
}
|
||||
return strings.Split(gamedata.GetStringValue(data, "Product_Type"), ",")
|
||||
}
|
||||
|
||||
func GetEmitOrderProduce(EmitType string) []string {
|
||||
data, err := gamedata.GetDataByKey(CFG_MERGE_EMIT, EmitType)
|
||||
if err != nil {
|
||||
log.Debug("GetEmitProduce GetOne EmitType:%s not found", EmitType)
|
||||
return []string{}
|
||||
}
|
||||
return strings.Split(gamedata.GetStringValue(data, "Order_Type"), ",")
|
||||
}
|
||||
|
||||
// 获取单个数据
|
||||
func GetOne(Id int) (*gamedata.MergeDataRecord, error) {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, Id)
|
||||
if err != nil {
|
||||
log.Debug("MergeDataCfg GetOne Id:%v not found", Id)
|
||||
return &gamedata.MergeDataRecord{}, errors.New("not found")
|
||||
}
|
||||
return &gamedata.MergeDataRecord{
|
||||
Id: gamedata.GetIntValue(data, "Id"),
|
||||
Lv: gamedata.GetIntValue(data, "Lv"),
|
||||
MaxLv: gamedata.GetIntValue(data, "MaxLv"),
|
||||
SellType: gamedata.GetStringValue(data, "SellType"),
|
||||
SellNum: gamedata.GetIntValue(data, "SellNum"),
|
||||
SellDiamond: gamedata.GetIntValue(data, "SellDiamond"),
|
||||
Color: gamedata.GetStringValue(data, "Color"),
|
||||
Star: gamedata.GetIntValue(data, "Star"),
|
||||
Type: gamedata.GetStringValue(data, "Type"),
|
||||
Emit_Product: gamedata.GetStringValue(data, "Emit_Product"),
|
||||
CoolTime: gamedata.GetIntValue(data, "CoolTime"),
|
||||
Emit_Type: gamedata.GetStringValue(data, "Emit_Type"),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 根据id获取棋子获得的星星
|
||||
func GetStarById(Id int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, Id)
|
||||
if err != nil {
|
||||
log.Debug("MergeDataCfg GetOne Id:%v not found", Id)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Star")
|
||||
}
|
||||
|
||||
func GetNameById(Id int) string {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, Id)
|
||||
if err != nil {
|
||||
log.Debug("MergeDataCfg GetOne Id:%v not found", Id)
|
||||
return ""
|
||||
}
|
||||
return gamedata.GetStringValue(data, "Title")
|
||||
}
|
||||
|
||||
// 根据等级和颜色获取棋子id
|
||||
func GetChessIdByLvAndColor(Lv int, Color string) int {
|
||||
if Lv == 0 || Color == "" {
|
||||
return 0
|
||||
}
|
||||
data, err := gamedata.GetData(CFG_NAME)
|
||||
if err != nil {
|
||||
// log.Debug("MergeDataCfg GetChessIdByLvAndColor lv:%v Color:%v not found", Lv, Color)
|
||||
return 0
|
||||
}
|
||||
for k, v := range data {
|
||||
lv := gamedata.GetIntValue(v, "Lv")
|
||||
color := gamedata.GetStringValue(v, "Color")
|
||||
if Lv == lv && color == Color {
|
||||
Id, _ := strconv.Atoi(k)
|
||||
return Id
|
||||
}
|
||||
}
|
||||
// log.Debug("MergeDataCfg GetChessIdByLvAndColor lv:%v Color:%v not found", Lv, Color)
|
||||
return 0
|
||||
}
|
||||
|
||||
// 根据Id获取棋子等级
|
||||
func GetLvById(Id int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, Id)
|
||||
if err != nil {
|
||||
//log.Debug("GetLvById GetOne Id:%v not found", Id)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Lv")
|
||||
}
|
||||
|
||||
// 根据Id获取棋子最大等级
|
||||
func GetMaxLvById(Id int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, Id)
|
||||
if err != nil {
|
||||
// log.Debug("GetMaxLvById GetOne Id:%v not found", Id)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "MaxLv")
|
||||
}
|
||||
|
||||
// 根据Id获取棋子最大等级
|
||||
func GetMaxLvByColor(Color string) int {
|
||||
ChessId := GetChessIdByLvAndColor(1, Color)
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, ChessId)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "MaxLv")
|
||||
}
|
||||
|
||||
// 根据Id获取发射器最小等级
|
||||
func GetEmitMinLvById(Id string) int {
|
||||
data, err := gamedata.GetDataByKey(CFG_MERGE_EMIT, Id)
|
||||
if err != nil {
|
||||
// log.Debug("GetEmitMinLvById GetOne Id:%v not found", Id)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Emit_Min_Lv")
|
||||
}
|
||||
|
||||
// 根据Id获取发射器修正系数
|
||||
func GetEmitRatio(Id string) float64 {
|
||||
data, err := gamedata.GetDataByKey(CFG_MERGE_EMIT, Id)
|
||||
if err != nil {
|
||||
// log.Debug("GetEmitRatio GetOne Id:%v not found", Id)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetFloatValue(data, "Ratio")
|
||||
}
|
||||
|
||||
func GetEmitRetire(Id string) int {
|
||||
data, err := gamedata.GetDataByKey(CFG_MERGE_EMIT, Id)
|
||||
if err != nil {
|
||||
log.Debug("GetEmitRetire GetOne Id:%v not found", Id)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Retire")
|
||||
}
|
||||
|
||||
func GetEmitProductNumByColor(Id string) int {
|
||||
data, err := gamedata.GetData(CFG_MERGE_EMIT)
|
||||
if err != nil {
|
||||
log.Debug("GetEmitProductNumByColor GetOne Id:%v not found", Id)
|
||||
return 0
|
||||
}
|
||||
for _, v := range data {
|
||||
ColorList := strings.Split(gamedata.GetStringValue(v, "Product_Type"), ",")
|
||||
if GoUtil.InStringArray(Id, ColorList) {
|
||||
return len(strings.Split(gamedata.GetStringValue(v, "Product_Type"), ","))
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// 根据Id获取棋子类型
|
||||
func GetTypeById(Id int) string {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, Id)
|
||||
if err != nil {
|
||||
log.Debug("GetTypeById GetOne Id:%v not found", Id)
|
||||
return ""
|
||||
}
|
||||
return gamedata.GetStringValue(data, "Type")
|
||||
}
|
||||
|
||||
// 根据Id获取棋子类型
|
||||
func GetColorById(Id int) string {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, Id)
|
||||
if err != nil {
|
||||
log.Debug("GetColorById GetOne Id:%v not found", Id)
|
||||
return ""
|
||||
}
|
||||
return gamedata.GetStringValue(data, "Color")
|
||||
}
|
||||
|
||||
// 根据Id获取棋子类型
|
||||
func GetSellNumById(Id int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, Id)
|
||||
if err != nil {
|
||||
log.Debug("GetSellNumById GetOne Id:%v not found", Id)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "SellNum")
|
||||
}
|
||||
|
||||
// 根据Id获取发射器产出类型
|
||||
func GetEmitProduceType(Id int) []string {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, Id)
|
||||
if err != nil {
|
||||
log.Debug("GetEmitProduceType GetOne Id:%v not found", Id)
|
||||
return []string{}
|
||||
}
|
||||
|
||||
return strings.Split(gamedata.GetStringValue(data, "Emit_Product"), ",")
|
||||
}
|
||||
|
||||
// 根据Id获取发射器产出类型
|
||||
func GetEmitProduceChessType(Id int) []string {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, Id)
|
||||
if err != nil {
|
||||
//log.Debug("GetEmitProduceChessType GetOne Id:%v not found", Id)
|
||||
return []string{}
|
||||
}
|
||||
|
||||
value := gamedata.GetStringValue(data, "Product_Type")
|
||||
if value == "" {
|
||||
return []string{}
|
||||
}
|
||||
return strings.Split(value, ",")
|
||||
}
|
||||
|
||||
// 根据Id获取发射器Id
|
||||
func GetEmitId(Id int) string {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, Id)
|
||||
if err != nil {
|
||||
// log.Debug("GetEmitId GetOne Id:%v not found", Id)
|
||||
return ""
|
||||
}
|
||||
|
||||
return gamedata.GetStringValue(data, "Emit_ID")
|
||||
}
|
||||
|
||||
func GetAllId() []int {
|
||||
data, err := gamedata.GetData(CFG_NAME)
|
||||
if err != nil {
|
||||
return []int{}
|
||||
}
|
||||
key := make([]int, 0, len(data))
|
||||
for k := range data {
|
||||
key = append(key, GoUtil.Int(k))
|
||||
}
|
||||
return key
|
||||
}
|
||||
|
||||
func GetEmitType(Id int) string {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, Id)
|
||||
if err != nil {
|
||||
log.Debug("GetEmitType GetOne Id:%v not found", Id)
|
||||
return ""
|
||||
}
|
||||
|
||||
return gamedata.GetStringValue(data, "Emit_Type")
|
||||
}
|
||||
|
||||
func GetEmitN(EmitSeries string) int {
|
||||
data, err := gamedata.GetDataByKey(CFG_MERGE_EMIT, EmitSeries)
|
||||
if err != nil {
|
||||
log.Debug("GetEmitN GetOne EmitSeries:%v not found", EmitSeries)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "N")
|
||||
}
|
||||
|
||||
// 获取常量
|
||||
func GetConst(Key string) string {
|
||||
data, err := gamedata.GetDataByKey(CONST_NAME, Key)
|
||||
if err != nil {
|
||||
log.Debug("GetConst GetOne Id:%s not found", Key)
|
||||
return ""
|
||||
}
|
||||
|
||||
return gamedata.GetStringValue(data, "Value")
|
||||
}
|
||||
|
||||
// 获取常量
|
||||
func GetConstInt(Key string) int {
|
||||
data, err := gamedata.GetDataByKey(CONST_NAME, Key)
|
||||
if err != nil {
|
||||
log.Debug("GetConst GetOne Id:%s not found", Key)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
func GetExtraEmitId() map[string]struct{} {
|
||||
Value := GetConst("EmitId_Extra_Order")
|
||||
arr := strings.Split(Value, ",")
|
||||
var r = make(map[string]struct{})
|
||||
for _, v := range arr {
|
||||
r[v] = struct{}{}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func GetChessBagMaxGrid() int {
|
||||
return GetConstInt("chess_bag_max")
|
||||
}
|
||||
|
||||
func GetChessBagBugNum() int {
|
||||
return GetConstInt("chess_bag_buy")
|
||||
}
|
||||
|
||||
func GetChessBagInitNum() int {
|
||||
return GetConstInt("chess_bag_init")
|
||||
}
|
||||
|
||||
func GetSourceChestItem() []*item.Item {
|
||||
data, err := gamedata.GetDataByKey(CONST_NAME, "source_chest_reward")
|
||||
if err != nil {
|
||||
log.Debug("GetSourceChestItem GetOne not found")
|
||||
return nil
|
||||
}
|
||||
|
||||
Str := gamedata.GetStringValue(data, "Value")
|
||||
A1 := strings.Split(Str, "|")
|
||||
var r []*item.Item
|
||||
if len(A1) < 2 {
|
||||
return r
|
||||
}
|
||||
A2 := strings.Split(A1[0], "/")
|
||||
A3 := GoUtil.StringToInt(A2)
|
||||
A4 := GoUtil.RandSlice(A3)
|
||||
r = append(r, item.NewItem(item.ITEM_DIAMOND_ID, A4))
|
||||
|
||||
B2 := strings.Split(A1[1], "/")
|
||||
B3 := GoUtil.StringToInt(B2)
|
||||
B4 := GoUtil.RandSlice(B3)
|
||||
r = append(r, item.NewItem(item.ITEM_ENERGY_ID, B4))
|
||||
return r
|
||||
}
|
||||
|
||||
func GetHighSourceChestItem() []*item.Item {
|
||||
data, err := gamedata.GetDataByKey(CONST_NAME, "high_source_chest_reward")
|
||||
if err != nil {
|
||||
log.Debug("GetHighSourceChestItem GetOne not found")
|
||||
return nil
|
||||
}
|
||||
Str := gamedata.GetStringValue(data, "Value")
|
||||
A1 := strings.Split(Str, "|")
|
||||
var r []*item.Item
|
||||
if len(A1) < 2 {
|
||||
return r
|
||||
}
|
||||
A2 := strings.Split(A1[0], "/")
|
||||
A3 := GoUtil.StringToInt(A2)
|
||||
A4 := GoUtil.RandSlice(A3)
|
||||
r = append(r, item.NewItem(item.ITEM_DIAMOND_ID, A4))
|
||||
|
||||
B2 := strings.Split(A1[1], "/")
|
||||
B3 := GoUtil.StringToInt(B2)
|
||||
B4 := GoUtil.RandSlice(B3)
|
||||
r = append(r, item.NewItem(item.ITEM_ENERGY_ID, B4))
|
||||
return r
|
||||
}
|
||||
|
||||
func GetRetireReward() []*item.Item {
|
||||
data, err := gamedata.GetDataByKey(CONST_NAME, "retire_reward")
|
||||
if err != nil {
|
||||
log.Debug("GetRetireReward GetOne not found")
|
||||
return nil
|
||||
}
|
||||
return gamedata.GetItemList(data, "Value")
|
||||
}
|
||||
|
||||
func DynamicLevRev(Lv int, EmitId int, Color string) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, EmitId)
|
||||
if err != nil {
|
||||
// log.Debug("DynamicLev GetOne EmitId:%v not found", EmitId)
|
||||
return Lv
|
||||
}
|
||||
DynamicLv := gamedata.GetStringValue(data, "Dynamic")
|
||||
if DynamicLv == "" {
|
||||
return Lv
|
||||
}
|
||||
Arr := strings.Split(DynamicLv, ",")
|
||||
for _, v := range Arr {
|
||||
Arr2 := strings.Split(v, "=")
|
||||
if len(Arr2) != 2 {
|
||||
continue
|
||||
}
|
||||
if Color == Arr2[0] {
|
||||
NewLv, _ := strconv.Atoi(Arr2[1])
|
||||
return Lv + NewLv
|
||||
}
|
||||
}
|
||||
return Lv
|
||||
}
|
||||
func DynamicLev(Lv int, EmitId int, Color string) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, EmitId)
|
||||
if err != nil {
|
||||
//log.Debug("DynamicLev GetOne EmitId:%v not found", EmitId)
|
||||
return Lv
|
||||
}
|
||||
DynamicLv := gamedata.GetStringValue(data, "Dynamic")
|
||||
if DynamicLv == "" {
|
||||
return Lv
|
||||
}
|
||||
Arr := strings.Split(DynamicLv, ",")
|
||||
for _, v := range Arr {
|
||||
Arr2 := strings.Split(v, "=")
|
||||
if len(Arr2) != 2 {
|
||||
continue
|
||||
}
|
||||
if Color == Arr2[0] {
|
||||
NewLv, _ := strconv.Atoi(Arr2[1])
|
||||
return Lv - NewLv
|
||||
}
|
||||
}
|
||||
return Lv
|
||||
}
|
||||
func DynamicLev2(Lv int, EmitId int, Color1 string, Color2 string) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, EmitId)
|
||||
if err != nil {
|
||||
//log.Debug("DynamicLev GetOne EmitId:%v not found", EmitId)
|
||||
return Lv
|
||||
}
|
||||
DynamicLv := gamedata.GetStringValue(data, "Dynamic")
|
||||
if DynamicLv == "" {
|
||||
return Lv
|
||||
}
|
||||
Arr := strings.Split(DynamicLv, ",")
|
||||
BaseLv := Lv
|
||||
for _, v := range Arr {
|
||||
Arr2 := strings.Split(v, "=")
|
||||
if len(Arr2) != 2 {
|
||||
continue
|
||||
}
|
||||
if Color1 == Arr2[0] {
|
||||
NewLv, _ := strconv.Atoi(Arr2[1])
|
||||
BaseLv = Lv + NewLv
|
||||
}
|
||||
}
|
||||
for _, v := range Arr {
|
||||
Arr2 := strings.Split(v, "=")
|
||||
if len(Arr2) != 2 {
|
||||
continue
|
||||
}
|
||||
if Color2 == Arr2[0] {
|
||||
NewLv, _ := strconv.Atoi(Arr2[1])
|
||||
return BaseLv - NewLv
|
||||
}
|
||||
}
|
||||
return Lv
|
||||
}
|
||||
|
||||
func DynamicAdjust(EmitId int, Color string, EnergyMul int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, EmitId)
|
||||
if err != nil {
|
||||
//log.Debug("DynamicLev GetOne EmitId:%v not found", EmitId)
|
||||
return 0
|
||||
}
|
||||
DynamicLv := ""
|
||||
switch EnergyMul {
|
||||
case 0:
|
||||
DynamicLv = gamedata.GetStringValue(data, "Dynamic")
|
||||
case 1, 2:
|
||||
DynamicLv = gamedata.GetStringValue(data, "Dynamic1")
|
||||
case 3, 4:
|
||||
DynamicLv = gamedata.GetStringValue(data, "Dynamic2")
|
||||
default:
|
||||
DynamicLv = gamedata.GetStringValue(data, "Dynamic3")
|
||||
}
|
||||
|
||||
if DynamicLv == "" {
|
||||
return 0
|
||||
}
|
||||
Arr := strings.Split(DynamicLv, ",")
|
||||
for _, v := range Arr {
|
||||
Arr2 := strings.Split(v, "=")
|
||||
if len(Arr2) != 2 {
|
||||
continue
|
||||
}
|
||||
if Color == Arr2[0] {
|
||||
NewLv, _ := strconv.Atoi(Arr2[1])
|
||||
return NewLv
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func GetAdjust(EmitId int, Color string, EnergyMul int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, EmitId)
|
||||
if err != nil {
|
||||
//log.Debug("DynamicLev GetOne EmitId:%v not found", EmitId)
|
||||
return 0
|
||||
}
|
||||
AdjustLv := ""
|
||||
switch EnergyMul {
|
||||
case 0:
|
||||
AdjustLv = gamedata.GetStringValue(data, "Dynamic")
|
||||
case 1, 2:
|
||||
AdjustLv = gamedata.GetStringValue(data, "Dynamic1")
|
||||
case 3, 4:
|
||||
AdjustLv = gamedata.GetStringValue(data, "Dynamic2")
|
||||
default:
|
||||
AdjustLv = gamedata.GetStringValue(data, "Dynamic3")
|
||||
}
|
||||
if AdjustLv == "" {
|
||||
return 0
|
||||
}
|
||||
Arr := strings.Split(AdjustLv, ",")
|
||||
for _, v := range Arr {
|
||||
Arr2 := strings.Split(v, "=")
|
||||
if len(Arr2) != 2 {
|
||||
continue
|
||||
}
|
||||
if Color == Arr2[0] {
|
||||
NewLv, _ := strconv.Atoi(Arr2[1])
|
||||
return NewLv
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func GetSellDiamondMul(EmitId int, Color string) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, EmitId)
|
||||
if err != nil {
|
||||
log.Debug("GetSellDiamondMul GetOne EmitId:%v not found", EmitId)
|
||||
return 0
|
||||
}
|
||||
ProductEmit := gamedata.GetStringValue(data, "Emit_Product")
|
||||
if ProductEmit == "" {
|
||||
return 1
|
||||
}
|
||||
Arr := strings.Split(ProductEmit, ",")
|
||||
if Color == Arr[0] {
|
||||
return 1
|
||||
}
|
||||
if !GoUtil.InStringArray(Color, Arr) {
|
||||
return 1
|
||||
}
|
||||
Emit_List := gamedata.GetStringValue(data, "Emit_List")
|
||||
MainProb := getColorProb(Emit_List, Arr[0])
|
||||
SubProb := getColorProb(Emit_List, Color)
|
||||
return int(MainProb / SubProb)
|
||||
}
|
||||
|
||||
func getColorProb(Emit_List string, Color string) float64 {
|
||||
Arr := strings.Split(Emit_List, ",")
|
||||
Prob := 0.0
|
||||
for _, v := range Arr {
|
||||
Arr2 := strings.Split(v, "=")
|
||||
A1 := GoUtil.Int(Arr2[0])
|
||||
A2, _ := strconv.ParseFloat(Arr2[1], 64)
|
||||
A1Color := GetColorById(A1)
|
||||
if A1Color != Color {
|
||||
continue
|
||||
}
|
||||
Prob += A2 * float64(A1%10)
|
||||
}
|
||||
return Prob
|
||||
}
|
||||
|
||||
func GetMergeStar(MergeList []int) int {
|
||||
Star := 0
|
||||
for _, v := range MergeList {
|
||||
Star += GetStarById(v)
|
||||
}
|
||||
return Star
|
||||
}
|
||||
|
||||
func GetAllChessBySeries(Series string) []int {
|
||||
data, err := gamedata.GetData(CFG_NAME)
|
||||
ProductList := GetEmitProduce(Series)
|
||||
if err != nil {
|
||||
return []int{}
|
||||
}
|
||||
var r []int
|
||||
for k, v := range data {
|
||||
Type := gamedata.GetStringValue(v, "Type")
|
||||
if Type == "Emitter" {
|
||||
EmitId := gamedata.GetStringValue(v, "Emit_ID")
|
||||
if EmitId == Series {
|
||||
r = append(r, GoUtil.Int(k))
|
||||
}
|
||||
}
|
||||
if Type == "Product" {
|
||||
Color := gamedata.GetStringValue(v, "Color")
|
||||
if GoUtil.InStringArray(Color, ProductList) {
|
||||
r = append(r, GoUtil.Int(k))
|
||||
}
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
130
src/server/conf/mining/mining_cfg.go
Normal file
130
src/server/conf/mining/mining_cfg.go
Normal file
@ -0,0 +1,130 @@
|
||||
package miningCfg
|
||||
|
||||
import (
|
||||
"server/game/mod/item"
|
||||
GoUtil "server/game_util"
|
||||
"server/gamedata"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
CFG_MINING_TEMPLATE = "MiningTemplate"
|
||||
CFG_MINING_JACKPOT = "MiningJackpot"
|
||||
CFG_MINING_GEM = "MiningGem"
|
||||
CFG_MINING_PASS = "MiningPass"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gamedata.InitCfg(CFG_MINING_TEMPLATE)
|
||||
gamedata.InitCfg(CFG_MINING_JACKPOT)
|
||||
gamedata.InitCfg(CFG_MINING_GEM)
|
||||
gamedata.InitCfg(CFG_MINING_PASS)
|
||||
}
|
||||
|
||||
func GetTemplate(Id int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_MINING_TEMPLATE, Id)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Template")
|
||||
}
|
||||
|
||||
func GetActivityItemId(Id int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_MINING_TEMPLATE, Id)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "ItemId")
|
||||
}
|
||||
|
||||
func GetLoseItem(Id int) []*item.Item {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_MINING_TEMPLATE, Id)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return gamedata.GetItemList(data, "ItemCost")
|
||||
}
|
||||
|
||||
func GetStartItemNum(Id int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_MINING_TEMPLATE, Id)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "StartItemNum")
|
||||
}
|
||||
|
||||
func GetPassArea(Id int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_MINING_PASS, Id)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
Area := gamedata.GetStringValue(data, "Area")
|
||||
strArr := strings.Split(Area, "*")
|
||||
a, _ := strconv.Atoi(strArr[0])
|
||||
b, _ := strconv.Atoi(strArr[1])
|
||||
return a * b
|
||||
}
|
||||
|
||||
func GetPassGem(Id int) []int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_MINING_PASS, Id)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
Gem := gamedata.GetStringValue(data, "Gem")
|
||||
strArr := strings.Split(Gem, "|")
|
||||
result := make([]int, 0, len(strArr))
|
||||
for _, v := range strArr {
|
||||
a, _ := strconv.Atoi(v)
|
||||
result = append(result, a)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func GetRandItem() []*item.Item {
|
||||
data, err := gamedata.GetData(CFG_MINING_JACKPOT)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
ProbMap := make(map[int]int)
|
||||
for k, v := range data {
|
||||
Id := GoUtil.Int(k)
|
||||
ProbMap[Id] = gamedata.GetIntValue(v, "Prob")
|
||||
}
|
||||
RandId := GoUtil.RandMap(ProbMap)
|
||||
Info, _ := gamedata.GetDataByIntKey(CFG_MINING_JACKPOT, RandId)
|
||||
return gamedata.GetItemList(Info, "Items")
|
||||
}
|
||||
|
||||
func GetPassItem(Id int, orderFactor int) []*item.Item {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_MINING_PASS, Id)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
items := gamedata.GetItemList(data, "Items")
|
||||
starReward := gamedata.GetIntValue(data, "StarReward")
|
||||
var starnum int
|
||||
if starReward > 0 {
|
||||
starnum = int((float64(starReward) * float64(orderFactor) / 500)) * 5
|
||||
if starnum > 0 {
|
||||
items = append(items, &item.Item{
|
||||
Id: item.ITEM_STAR_ID,
|
||||
Num: starnum,
|
||||
})
|
||||
}
|
||||
}
|
||||
return items
|
||||
}
|
||||
|
||||
func GetPassItemList(orderFactor int) map[int][]*item.Item {
|
||||
data, err := gamedata.GetData(CFG_MINING_PASS)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
result := make(map[int][]*item.Item)
|
||||
for k := range data {
|
||||
Id := GoUtil.Int(k)
|
||||
result[Id] = GetPassItem(Id, orderFactor)
|
||||
}
|
||||
return result
|
||||
}
|
||||
43
src/server/conf/notification/notification_cfg.go
Normal file
43
src/server/conf/notification/notification_cfg.go
Normal file
@ -0,0 +1,43 @@
|
||||
package notification_cfg
|
||||
|
||||
import "server/gamedata"
|
||||
|
||||
const (
|
||||
CFG_NOTIFICATION = "Notification"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gamedata.InitCfg(CFG_NOTIFICATION)
|
||||
}
|
||||
|
||||
func GetFriendApplyNotificationCooldown() int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NOTIFICATION, 2)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Cooldown")
|
||||
}
|
||||
|
||||
func GetPetroomGameNotificationCooldown() (int, int) {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NOTIFICATION, 1)
|
||||
if err != nil {
|
||||
return 0, 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Cooldown"), gamedata.GetIntValue(data, "DailyLimit")
|
||||
}
|
||||
|
||||
func GetPetroomGameNotificationMsg() (string, string) {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NOTIFICATION, 1)
|
||||
if err != nil {
|
||||
return "", ""
|
||||
}
|
||||
return gamedata.GetStringValue(data, "TitleKey"), gamedata.GetStringValue(data, "InfoKey")
|
||||
}
|
||||
|
||||
func GetFriendApplyNotificationMsg() (string, string) {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NOTIFICATION, 2)
|
||||
if err != nil {
|
||||
return "", ""
|
||||
}
|
||||
return gamedata.GetStringValue(data, "TitleKey"), gamedata.GetStringValue(data, "InfoKey")
|
||||
}
|
||||
@ -1,38 +0,0 @@
|
||||
package orderCfg
|
||||
|
||||
import (
|
||||
"server/gamedata"
|
||||
)
|
||||
|
||||
const (
|
||||
CFG_ORDER_DATA = "OrderData"
|
||||
CFG_ORDER_CHESS_DATA = "OrderChessData"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gamedata.InitCfg(CFG_ORDER_DATA)
|
||||
gamedata.InitCfg(CFG_ORDER_CHESS_DATA)
|
||||
}
|
||||
|
||||
func GetLvMin(EnergyMul int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_ORDER_DATA, EnergyMul)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "LvMin")
|
||||
}
|
||||
|
||||
func GetLvMax(EnergyMul, N int) int {
|
||||
if v, ok := gamedata.G_AllConfigsJsonData["OrderChessData"]; ok {
|
||||
data := v.GetData()
|
||||
for _, v := range data {
|
||||
dEnergy := gamedata.GetIntValue(v, "EnergyMul")
|
||||
Min := gamedata.GetIntValue(v, "MinN")
|
||||
Max := gamedata.GetIntValue(v, "MaxN")
|
||||
if dEnergy == EnergyMul && N >= Min && N <= Max {
|
||||
return gamedata.GetIntValue(v, "MaxLv")
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
190
src/server/conf/order/order_cfg.go
Normal file
190
src/server/conf/order/order_cfg.go
Normal file
@ -0,0 +1,190 @@
|
||||
package orderCfg
|
||||
|
||||
import (
|
||||
"math"
|
||||
"server/gamedata"
|
||||
"sort"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const (
|
||||
CFG_ORDER_DATA = "OrderData"
|
||||
CFG_ORDER_CHESS_DATA = "OrderChessData"
|
||||
CFG_ORDER_NUM_DATA = "OrderNumData"
|
||||
CFG_START_ORDER = "StartOrder"
|
||||
CFG_CONST = "OrderConst"
|
||||
CFG_ORDER_SCENE = "OrderScene"
|
||||
CFG_ORDER_K = "OrderK"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gamedata.InitCfg(CFG_ORDER_DATA)
|
||||
gamedata.InitCfg(CFG_ORDER_CHESS_DATA)
|
||||
gamedata.InitCfg(CFG_ORDER_NUM_DATA)
|
||||
gamedata.InitCfg(CFG_START_ORDER)
|
||||
gamedata.InitCfg(CFG_CONST)
|
||||
gamedata.InitCfg(CFG_ORDER_SCENE)
|
||||
gamedata.InitCfg(CFG_ORDER_K)
|
||||
}
|
||||
|
||||
func GetOrderK(Lv int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_ORDER_K, Lv)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
Energy := gamedata.GetIntValue(data, "Energy")
|
||||
K := gamedata.GetFloatValue(data, "K")
|
||||
return int(math.Round(float64(Energy)*K/10) * 10)
|
||||
}
|
||||
|
||||
func GetOrderFactor(Scene int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_ORDER_SCENE, Scene)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Factor")
|
||||
}
|
||||
|
||||
func GetEmitExtraOrder() string {
|
||||
data, err := gamedata.GetDataByKey(CFG_CONST, "EmitId_Extra_Order")
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return gamedata.GetStringValue(data, "Value")
|
||||
}
|
||||
|
||||
func GetLvMin(EnergyMul int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_ORDER_DATA, EnergyMul)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "LvMin")
|
||||
}
|
||||
|
||||
func GetLvMax(EnergyMul, N int) int {
|
||||
data, err := gamedata.GetData(CFG_ORDER_CHESS_DATA)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
for _, v := range data {
|
||||
dEnergy := gamedata.GetIntValue(v, "EnergyMul")
|
||||
Min := gamedata.GetIntValue(v, "MinN")
|
||||
Max := gamedata.GetIntValue(v, "MaxN")
|
||||
if dEnergy == EnergyMul {
|
||||
if N >= Min && N <= Max {
|
||||
return gamedata.GetIntValue(v, "MaxLv")
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func GetOrderNum(Level int) int {
|
||||
data, err := gamedata.GetData(CFG_ORDER_NUM_DATA)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
for _, v := range data {
|
||||
Min := gamedata.GetIntValue(v, "Min")
|
||||
Max := gamedata.GetIntValue(v, "Max")
|
||||
if Level >= Min && Level <= Max {
|
||||
return gamedata.GetIntValue(v, "Num")
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func GetStartOrderInfo(Id int) (int, int) {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_START_ORDER, Id)
|
||||
if err != nil {
|
||||
return -1, -1
|
||||
}
|
||||
return gamedata.GetIntValue(data, "group"), gamedata.GetIntValue(data, "step")
|
||||
}
|
||||
|
||||
func GetStartOrderList() []*gamedata.StartOrderData {
|
||||
data, err := gamedata.GetData(CFG_START_ORDER)
|
||||
if err != nil {
|
||||
return []*gamedata.StartOrderData{}
|
||||
}
|
||||
ret := make([]*gamedata.StartOrderData, 0, len(data))
|
||||
for k, v := range data {
|
||||
OrderId, _ := strconv.Atoi(k)
|
||||
ret = append(ret, &gamedata.StartOrderData{
|
||||
Id: OrderId,
|
||||
MergeList: gamedata.GetIntSliceValue(v, "merge_id_list"),
|
||||
Appear: gamedata.GetStringValue(v, "appear"),
|
||||
Preview: gamedata.GetStringValue(v, "preview"),
|
||||
Items: gamedata.GetItemList(v, "reward"),
|
||||
Group: gamedata.GetIntValue(v, "group"),
|
||||
Step: gamedata.GetIntValue(v, "step"),
|
||||
})
|
||||
}
|
||||
sort.Slice(ret, func(i, j int) bool {
|
||||
return ret[i].Id < ret[j].Id
|
||||
})
|
||||
return ret
|
||||
}
|
||||
|
||||
func GetStartOrderByStep(id int) []*gamedata.StartOrderData {
|
||||
data, err := gamedata.GetData(CFG_START_ORDER)
|
||||
if err != nil {
|
||||
return []*gamedata.StartOrderData{}
|
||||
}
|
||||
ret := make([]*gamedata.StartOrderData, len(data))
|
||||
for k, v := range data {
|
||||
stepVal := gamedata.GetIntValue(v, "step")
|
||||
if int(stepVal) == id {
|
||||
OrderId, _ := strconv.Atoi(k)
|
||||
ret = append(ret, &gamedata.StartOrderData{
|
||||
Id: OrderId,
|
||||
Step: int(stepVal),
|
||||
MergeList: gamedata.GetIntSliceValue(v, "merge_id_list"),
|
||||
})
|
||||
}
|
||||
}
|
||||
sort.Slice(ret, func(i, j int) bool {
|
||||
return ret[i].Id < ret[j].Id
|
||||
})
|
||||
return ret
|
||||
}
|
||||
|
||||
func GetStartOrderById(id int) *gamedata.StartOrderData {
|
||||
data, err := gamedata.GetData(CFG_START_ORDER)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
v, ok := data[strconv.Itoa(id)]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
stepVal := gamedata.GetIntValue(v, "step")
|
||||
return &gamedata.StartOrderData{
|
||||
Id: id,
|
||||
Step: int(stepVal),
|
||||
MergeList: gamedata.GetIntSliceValue(v, "merge_id_list"),
|
||||
}
|
||||
}
|
||||
|
||||
func GetMaxStep() int {
|
||||
data, err := gamedata.GetData(CFG_START_ORDER)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
max := 0
|
||||
for _, v := range data {
|
||||
stepVal := gamedata.GetIntValue(v, "step")
|
||||
if int(stepVal) > max {
|
||||
max = int(stepVal)
|
||||
}
|
||||
}
|
||||
return max
|
||||
}
|
||||
|
||||
func GetOrderType(Id int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_START_ORDER, Id)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "type")
|
||||
}
|
||||
122
src/server/conf/pass/pass_cfg.go
Normal file
122
src/server/conf/pass/pass_cfg.go
Normal file
@ -0,0 +1,122 @@
|
||||
package passCfg
|
||||
|
||||
import (
|
||||
"server/game/mod/item"
|
||||
"server/gamedata"
|
||||
"slices"
|
||||
)
|
||||
|
||||
const (
|
||||
CFG_PASS_TEMPLATE = "PassTemplate"
|
||||
CFG_PASS = "Pass"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gamedata.InitCfg(CFG_PASS_TEMPLATE)
|
||||
gamedata.InitCfg(CFG_PASS)
|
||||
}
|
||||
|
||||
func GetTemplate(Id int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_PASS_TEMPLATE, Id)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Template")
|
||||
}
|
||||
|
||||
func GetActivityItemId(Id int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_PASS_TEMPLATE, Id)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "ItemId")
|
||||
}
|
||||
|
||||
func GetLowChargeId(Id int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_PASS_TEMPLATE, Id)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "LowChargeId")
|
||||
}
|
||||
|
||||
func GetHighChargeId(Id int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_PASS_TEMPLATE, Id)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "HighChargeId")
|
||||
}
|
||||
|
||||
func GetNewLevel(Template int, Score int, Reward []int) []int {
|
||||
data, err := gamedata.GetData(CFG_PASS)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
NewReward := make([]int, 0, len(data))
|
||||
for _, v := range data {
|
||||
if gamedata.GetIntValue(v, "Template") != Template {
|
||||
continue
|
||||
}
|
||||
LevelScore := gamedata.GetIntValue(v, "TotalScore")
|
||||
Index := gamedata.GetIntValue(v, "Level")
|
||||
if Score >= LevelScore && !slices.Contains(Reward, Index) {
|
||||
NewReward = append(NewReward, Index)
|
||||
}
|
||||
}
|
||||
return NewReward
|
||||
}
|
||||
|
||||
func GetFreeChargeItems(Template int, Reward []int) []*item.Item {
|
||||
data, err := gamedata.GetData(CFG_PASS)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
Items := make([]*item.Item, 0, len(data))
|
||||
for _, v := range data {
|
||||
if gamedata.GetIntValue(v, "Template") != Template {
|
||||
continue
|
||||
}
|
||||
Index := gamedata.GetIntValue(v, "Level")
|
||||
if slices.Contains(Reward, Index) {
|
||||
Items = append(Items, gamedata.GetItemList(data, "FreeReward")...)
|
||||
}
|
||||
}
|
||||
return Items
|
||||
}
|
||||
|
||||
func GetLowChargeItems(Template int, Reward []int) []*item.Item {
|
||||
data, err := gamedata.GetData(CFG_PASS)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
Items := make([]*item.Item, 0, len(data))
|
||||
for _, v := range data {
|
||||
if gamedata.GetIntValue(v, "Template") != Template {
|
||||
continue
|
||||
}
|
||||
Index := gamedata.GetIntValue(v, "Level")
|
||||
if slices.Contains(Reward, Index) {
|
||||
Items = append(Items, gamedata.GetItemList(data, "LowReward")...)
|
||||
}
|
||||
}
|
||||
return Items
|
||||
}
|
||||
|
||||
func GetHighChargeItems(Template int, Reward []int) []*item.Item {
|
||||
data, err := gamedata.GetData(CFG_PASS)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
Items := make([]*item.Item, 0, len(data))
|
||||
for _, v := range data {
|
||||
if gamedata.GetIntValue(v, "Template") != Template {
|
||||
continue
|
||||
}
|
||||
Index := gamedata.GetIntValue(v, "Level")
|
||||
if slices.Contains(Reward, Index) {
|
||||
Items = append(Items, gamedata.GetItemList(data, "HighReward")...)
|
||||
}
|
||||
}
|
||||
return Items
|
||||
}
|
||||
723
src/server/conf/playroom/playroom_cfg.go
Normal file
723
src/server/conf/playroom/playroom_cfg.go
Normal file
@ -0,0 +1,723 @@
|
||||
package playroomCfg
|
||||
|
||||
import (
|
||||
"server/game/mod/item"
|
||||
GoUtil "server/game_util"
|
||||
"server/gamedata"
|
||||
"strings"
|
||||
|
||||
"gitea.bywaystudios.com/pet_home/leaf/log"
|
||||
)
|
||||
|
||||
const (
|
||||
CFG_PLAYROOM_CONST = "PlayroomConst"
|
||||
CFG_PLAYROOM_DECORATE = "PlayroomDecorate"
|
||||
CFG_PLAYROOM_MOOD = "PlayroomMood"
|
||||
CFG_PLAYROOM_PHYSIOLOGY = "PlayroomPhysiology"
|
||||
CFG_PLAYROOM_PHYSIOLOGY_TYPE = "PlayroomPhysiologyType"
|
||||
CFG_PLAYROOM_SHOP = "PlayroomShop"
|
||||
CFG_PLAYROOM_DRESS = "PlayroomDress"
|
||||
CFG_PLAYROOM_AIR = "PlayroomAir"
|
||||
CFG_PLAYROOM_LOCK = "PlayroomLock"
|
||||
CFG_PLAYROOM_DAILYTASK = "PlayroomDailyTask"
|
||||
CFG_PLAYROOM_DAILYTASKREWARD = "PlayroomDailyTaskReward"
|
||||
CFG_PLAYROOM_TASKJACKPOT = "PlayroomTaskJackpot"
|
||||
CFG_PLAYROOM_ORDERITEM = "PlayroomOrderItem" // 订单物品
|
||||
)
|
||||
|
||||
func init() {
|
||||
gamedata.InitCfg(CFG_PLAYROOM_CONST)
|
||||
gamedata.InitCfg(CFG_PLAYROOM_DECORATE)
|
||||
gamedata.InitCfg(CFG_PLAYROOM_MOOD)
|
||||
gamedata.InitCfg(CFG_PLAYROOM_PHYSIOLOGY)
|
||||
gamedata.InitCfg(CFG_PLAYROOM_PHYSIOLOGY_TYPE)
|
||||
gamedata.InitCfg(CFG_PLAYROOM_SHOP)
|
||||
gamedata.InitCfg(CFG_PLAYROOM_DRESS)
|
||||
gamedata.InitCfg(CFG_PLAYROOM_AIR)
|
||||
gamedata.InitCfg(CFG_PLAYROOM_LOCK)
|
||||
gamedata.InitCfg(CFG_PLAYROOM_DAILYTASK)
|
||||
gamedata.InitCfg(CFG_PLAYROOM_DAILYTASKREWARD)
|
||||
gamedata.InitCfg(CFG_PLAYROOM_TASKJACKPOT)
|
||||
gamedata.InitCfg(CFG_PLAYROOM_ORDERITEM)
|
||||
}
|
||||
|
||||
func GetShopItem(Id int) (int, []*item.Item, int, int) {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_PLAYROOM_SHOP, Id)
|
||||
if err != nil {
|
||||
return 0, nil, 0, 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "ItemId"), gamedata.GetItemList(data, "Cost"), gamedata.GetIntValue(data, "Discount"), gamedata.GetIntValue(data, "Limit")
|
||||
}
|
||||
|
||||
func GetShopWeeklyLimit() map[int]gamedata.WeeklyDiscountInfo {
|
||||
r := make(map[int]gamedata.WeeklyDiscountInfo)
|
||||
data, err := gamedata.GetData(CFG_PLAYROOM_SHOP)
|
||||
if err != nil {
|
||||
return r
|
||||
}
|
||||
for k, v := range data {
|
||||
Id := GoUtil.Int(k)
|
||||
Limit := gamedata.GetIntValue(v, "Limit")
|
||||
if Limit == 0 {
|
||||
continue
|
||||
}
|
||||
r[Id] = gamedata.WeeklyDiscountInfo{
|
||||
Id: Id,
|
||||
Discount: gamedata.GetIntValue(v, "Discount"),
|
||||
WeeklyLimit: Limit,
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func GetShopWish(Id int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_PLAYROOM_SHOP, Id)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Wish")
|
||||
}
|
||||
|
||||
func GetUnLockLv() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_PLAYROOM_CONST, "Lv")
|
||||
if err != nil {
|
||||
return 999
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
func GetGameOutline() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_PLAYROOM_CONST, "GameOutline")
|
||||
if err != nil {
|
||||
return 999
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
func GetChipNum() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_PLAYROOM_CONST, "ChipNum")
|
||||
if err != nil {
|
||||
return 12
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
func GetOrderStar() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_PLAYROOM_CONST, "Star")
|
||||
if err != nil {
|
||||
return 1000
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
func GetRewardStar() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_PLAYROOM_CONST, "RewardStar")
|
||||
if err != nil {
|
||||
return 1000
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
func GetTriggerCd() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_PLAYROOM_CONST, "CD")
|
||||
if err != nil {
|
||||
return 1000
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
func GetFoodItem() []int {
|
||||
data, err := gamedata.GetDataByKey(CFG_PLAYROOM_CONST, "Food")
|
||||
if err != nil {
|
||||
return []int{}
|
||||
}
|
||||
r := make([]int, 0, len(data))
|
||||
for _, v := range strings.Split(gamedata.GetStringValue(data, "Value"), ",") {
|
||||
if v == "" {
|
||||
continue
|
||||
}
|
||||
Id := GoUtil.Int(v)
|
||||
r = append(r, Id)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func GetCleanItem() []int {
|
||||
data, err := gamedata.GetDataByKey(CFG_PLAYROOM_CONST, "Clean")
|
||||
if err != nil {
|
||||
return []int{}
|
||||
}
|
||||
r := make([]int, 0, len(data))
|
||||
for _, v := range strings.Split(gamedata.GetStringValue(data, "Value"), ",") {
|
||||
if v == "" {
|
||||
continue
|
||||
}
|
||||
Id := GoUtil.Int(v)
|
||||
r = append(r, Id)
|
||||
}
|
||||
return r
|
||||
}
|
||||
func GetToyItem() []int {
|
||||
data, err := gamedata.GetDataByKey(CFG_PLAYROOM_CONST, "Toy")
|
||||
if err != nil {
|
||||
return []int{}
|
||||
}
|
||||
r := make([]int, 0, len(data))
|
||||
for _, v := range strings.Split(gamedata.GetStringValue(data, "Value"), ",") {
|
||||
if v == "" {
|
||||
continue
|
||||
}
|
||||
Id := GoUtil.Int(v)
|
||||
r = append(r, Id)
|
||||
}
|
||||
return r
|
||||
}
|
||||
func GetDailyItem() []int {
|
||||
data, err := gamedata.GetDataByKey(CFG_PLAYROOM_CONST, "Daily")
|
||||
if err != nil {
|
||||
return []int{}
|
||||
}
|
||||
r := make([]int, 0, len(data))
|
||||
for _, v := range strings.Split(gamedata.GetStringValue(data, "Value"), ",") {
|
||||
if v == "" {
|
||||
continue
|
||||
}
|
||||
Id := GoUtil.Int(v)
|
||||
r = append(r, Id)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func GetPremiumItem() []int {
|
||||
data, err := gamedata.GetDataByKey(CFG_PLAYROOM_CONST, "PremiumItem")
|
||||
if err != nil {
|
||||
return []int{}
|
||||
}
|
||||
r := make([]int, 0, len(data))
|
||||
for _, v := range strings.Split(gamedata.GetStringValue(data, "Value"), ",") {
|
||||
if v == "" {
|
||||
continue
|
||||
}
|
||||
Id := GoUtil.Int(v)
|
||||
r = append(r, Id)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func GetInteractNum() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_PLAYROOM_CONST, "InteractNum")
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
func GetInteractUnlock() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_PLAYROOM_CONST, "InteractUnlock")
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
func GetVisitorItem() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_PLAYROOM_CONST, "VisitorItem")
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
func GetWorkItem() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_PLAYROOM_CONST, "WorkItem")
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
func GetWorkChargeId() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_PLAYROOM_CONST, "WorkChargeId")
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
func GetJackpotNum() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_PLAYROOM_CONST, "Jackpot")
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
func GetInteract(Id, Type int) (int, []*item.Item, int) {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_PLAYROOM_MOOD, Id)
|
||||
if err != nil {
|
||||
return 0, nil, 0
|
||||
}
|
||||
if Type == 1 {
|
||||
return gamedata.GetIntValue(data, "Type"), gamedata.GetItemList(data, "Cost"), gamedata.GetIntValue(data, "Effect")
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Type"), gamedata.GetItemList(data, "Cost2"), gamedata.GetIntValue(data, "Effect")
|
||||
}
|
||||
|
||||
func GetInteractPhysiology(Id int) (int, int) {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_PLAYROOM_MOOD, Id)
|
||||
if err != nil {
|
||||
return 0, 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "PType"), gamedata.GetIntValue(data, "PEffect")
|
||||
}
|
||||
|
||||
func GetInteractPExp(Id int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_PLAYROOM_MOOD, Id)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "PExp")
|
||||
}
|
||||
|
||||
func GetInitDecorate() []int {
|
||||
data, err := gamedata.GetData(CFG_PLAYROOM_DECORATE)
|
||||
if err != nil {
|
||||
return []int{}
|
||||
}
|
||||
r := make([]int, 0, len(data))
|
||||
for k, v := range data {
|
||||
if gamedata.GetIntValue(v, "Init") == 1 {
|
||||
r = append(r, GoUtil.Int(k))
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func GetDecorateList() []int {
|
||||
data, err := gamedata.GetData(CFG_PLAYROOM_DECORATE)
|
||||
if err != nil {
|
||||
return []int{}
|
||||
}
|
||||
r := make([]int, 0, len(data))
|
||||
for k := range data {
|
||||
r = append(r, GoUtil.Int(k))
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func GetBuyItem(Id int) ([]*item.Item, []*item.Item) {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_PLAYROOM_MOOD, Id)
|
||||
if err != nil {
|
||||
return nil, nil
|
||||
}
|
||||
return gamedata.GetItemList(data, "Cost2"), gamedata.GetItemList(data, "Buy")
|
||||
}
|
||||
|
||||
func GetPhysiologyMax(Id int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_PLAYROOM_PHYSIOLOGY_TYPE, Id)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Max")
|
||||
}
|
||||
|
||||
func GetPhysiologyDuration(Id int, Num int) int {
|
||||
data, err := gamedata.GetData(CFG_PLAYROOM_PHYSIOLOGY)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
for _, v := range data {
|
||||
Type := gamedata.GetIntValue(v, "Type")
|
||||
if Type != Id {
|
||||
continue
|
||||
}
|
||||
Min := gamedata.GetIntValue(v, "Min")
|
||||
Max := gamedata.GetIntValue(v, "Max")
|
||||
if Num >= Min && Num <= Max {
|
||||
return gamedata.GetIntValue(v, "Per") * 60
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func GetPhysiologyTypeList() []int {
|
||||
data, err := gamedata.GetData(CFG_PLAYROOM_PHYSIOLOGY_TYPE)
|
||||
if err != nil {
|
||||
return []int{}
|
||||
}
|
||||
r := make([]int, 0, len(data))
|
||||
for k := range data {
|
||||
r = append(r, GoUtil.Int(k))
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func GetMoodEffect(Id int) (int, int) {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_PLAYROOM_PHYSIOLOGY_TYPE, Id)
|
||||
if err != nil {
|
||||
return 0, 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "MType"), gamedata.GetIntValue(data, "MEffect")
|
||||
}
|
||||
|
||||
func IsStokeCat(Id int) bool {
|
||||
data, err := gamedata.GetDataByKey(CFG_PLAYROOM_CONST, "StokeCatId")
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value") == Id
|
||||
}
|
||||
|
||||
func IsTakeCat(Id int) bool {
|
||||
data, err := gamedata.GetDataByKey(CFG_PLAYROOM_CONST, "TakeCatId")
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
Ids := gamedata.GetIntSliceValue(data, "Value")
|
||||
return GoUtil.InArray(Id, Ids)
|
||||
}
|
||||
|
||||
func GetRoomPointInvite() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_PLAYROOM_CONST, "RoomPointInvite")
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
func GetRoomPointAdd() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_PLAYROOM_CONST, "RoomPointAdd")
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
func IsPlayCat(Id int) bool {
|
||||
data, err := gamedata.GetDataByKey(CFG_PLAYROOM_CONST, "PlayCatId")
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
Ids := gamedata.GetIntSliceValue(data, "Value")
|
||||
return GoUtil.InArray(Id, Ids)
|
||||
}
|
||||
|
||||
func GetInitAirList() []int {
|
||||
data, err := gamedata.GetData(CFG_PLAYROOM_AIR)
|
||||
if err != nil {
|
||||
return []int{}
|
||||
}
|
||||
r := make([]int, 0, len(data))
|
||||
for k, v := range data {
|
||||
if gamedata.GetIntValue(v, "Init") == 1 {
|
||||
r = append(r, GoUtil.Int(k))
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func GetAirList() []int {
|
||||
data, err := gamedata.GetData(CFG_PLAYROOM_AIR)
|
||||
if err != nil {
|
||||
return []int{}
|
||||
}
|
||||
r := make([]int, 0, len(data))
|
||||
for k := range data {
|
||||
r = append(r, GoUtil.Int(k))
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func GetInitDressList() []int {
|
||||
data, err := gamedata.GetData(CFG_PLAYROOM_DRESS)
|
||||
if err != nil {
|
||||
return []int{}
|
||||
}
|
||||
r := make([]int, 0, len(data))
|
||||
for k, v := range data {
|
||||
if gamedata.GetIntValue(v, "Init") == 1 {
|
||||
r = append(r, GoUtil.Int(k))
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func GetDressList() []int {
|
||||
data, err := gamedata.GetData(CFG_PLAYROOM_DRESS)
|
||||
if err != nil {
|
||||
return []int{}
|
||||
}
|
||||
r := make([]int, 0, len(data))
|
||||
for k := range data {
|
||||
r = append(r, GoUtil.Int(k))
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func GetDressPart(Id int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_PLAYROOM_DRESS, Id)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "IPart")
|
||||
}
|
||||
|
||||
func GetDressName(Id int) string {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_PLAYROOM_DRESS, Id)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return gamedata.GetStringValue(data, "Name")
|
||||
}
|
||||
|
||||
func GetUnlockNeed(Type int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_PLAYROOM_LOCK, Type)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Need")
|
||||
}
|
||||
|
||||
func GetUnlockName(Type int) string {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_PLAYROOM_LOCK, Type)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return gamedata.GetStringValue(data, "Name")
|
||||
}
|
||||
|
||||
func GetDailyTask(Type int) map[int]string {
|
||||
data, err := gamedata.GetData(CFG_PLAYROOM_DAILYTASK)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
r := make(map[int]string)
|
||||
r1 := make([]int, 0, len(data))
|
||||
r2 := make(map[int]string)
|
||||
for k, v := range data {
|
||||
if gamedata.GetIntValue(v, "Type") == Type {
|
||||
k1 := GoUtil.Int(k)
|
||||
r[k1] = gamedata.GetStringValue(v, "Task")
|
||||
r1 = append(r1, k1)
|
||||
}
|
||||
}
|
||||
daily_group_num := 0
|
||||
switch Type {
|
||||
case 1:
|
||||
daily_group_num = GetPlayroomTaskDailyNum1()
|
||||
case 2:
|
||||
daily_group_num = GetPlayroomTaskDailyNum2()
|
||||
}
|
||||
r3 := GoUtil.RandSliceNum(r1, daily_group_num)
|
||||
for _, v := range r3 {
|
||||
r2[v] = r[v]
|
||||
}
|
||||
return r2
|
||||
}
|
||||
|
||||
func GetDailyTaskType(Id int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_PLAYROOM_DAILYTASK, Id)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Type")
|
||||
}
|
||||
|
||||
func GetDailyTaskReward(Id int) []*item.Item {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_PLAYROOM_DAILYTASKREWARD, Id)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return gamedata.GetItemList(data, "Items")
|
||||
}
|
||||
|
||||
// 获取场景冲刺奖池
|
||||
func GetTaskJackpotProb() map[int]int {
|
||||
r := make(map[int]int)
|
||||
data, err := gamedata.GetData(CFG_PLAYROOM_TASKJACKPOT)
|
||||
if err != nil {
|
||||
log.Debug("GetTaskJackpotProb err:%v", err)
|
||||
return nil
|
||||
}
|
||||
for k, v := range data {
|
||||
Id := GoUtil.Int(k)
|
||||
r[Id] = gamedata.GetIntValue(v, "Prob")
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// 获取场景冲刺奖励
|
||||
func GetTaskJackpotReward(Id int) []*item.Item {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_PLAYROOM_TASKJACKPOT, Id)
|
||||
if err != nil {
|
||||
log.Debug("GetTaskJackpotReward err:%v", err)
|
||||
return nil
|
||||
}
|
||||
return gamedata.GetItemList(data, "Items")
|
||||
}
|
||||
|
||||
func GetPhysiologyList(MoodType int) []int {
|
||||
data, err := gamedata.GetData(CFG_PLAYROOM_PHYSIOLOGY_TYPE)
|
||||
if err != nil {
|
||||
return []int{}
|
||||
}
|
||||
r := make([]int, 0, len(data))
|
||||
for k, v := range data {
|
||||
if gamedata.GetIntValue(v, "MType") == MoodType {
|
||||
r = append(r, GoUtil.Int(k))
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func GetInteractIdBath() []int {
|
||||
return []int{11, 12, 13}
|
||||
}
|
||||
|
||||
func GetOrderItemByGrade(Grade int) map[int][]int {
|
||||
data, err := gamedata.GetData(CFG_PLAYROOM_ORDERITEM)
|
||||
if err != nil {
|
||||
log.Debug("GetOrderItemByGrade err:%v", err)
|
||||
return nil
|
||||
}
|
||||
r := make(map[int][]int)
|
||||
for k, v := range data {
|
||||
GradeStr := gamedata.GetStringValue(v, "Grade")
|
||||
GradeList := make([]int, 0)
|
||||
for _, v1 := range strings.Split(GradeStr, ",") {
|
||||
v2 := GoUtil.Int(v1)
|
||||
if v2 > 0 {
|
||||
GradeList = append(GradeList, v2)
|
||||
}
|
||||
}
|
||||
if !GoUtil.InArray(Grade, GradeList) {
|
||||
continue
|
||||
}
|
||||
Id := GoUtil.Int(k)
|
||||
Type := gamedata.GetIntValue(v, "Type")
|
||||
if Type == 0 {
|
||||
continue
|
||||
}
|
||||
if _, ok := r[Type]; !ok {
|
||||
r[Type] = make([]int, 0)
|
||||
}
|
||||
if Id == 0 {
|
||||
log.Debug("GetOrderItemByGrade Id is 0, Type:%v", Type)
|
||||
continue
|
||||
}
|
||||
r[Type] = append(r[Type], Id)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func GetOrderItemList() []int {
|
||||
data, err := gamedata.GetData(CFG_PLAYROOM_ORDERITEM)
|
||||
if err != nil {
|
||||
log.Debug("GetOrderItemList err:%v", err)
|
||||
return nil
|
||||
}
|
||||
r := make([]int, 0, len(data))
|
||||
for k := range data {
|
||||
Id := GoUtil.Int(k)
|
||||
if Id == 0 {
|
||||
log.Debug("GetOrderItemList Id is 0")
|
||||
continue
|
||||
}
|
||||
r = append(r, Id)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func GetPetOrderItemExpByList(ItemList []*item.Item) int {
|
||||
r := 0
|
||||
for _, v := range ItemList {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_PLAYROOM_ORDERITEM, v.Id)
|
||||
if err != nil {
|
||||
// log.Debug("GetPetOrderItemExpByList err:%v", err)
|
||||
continue
|
||||
}
|
||||
Star := gamedata.GetIntValue(data, "Star")
|
||||
r += Star * v.Num
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func GetShopItemAdNum(Id int) int {
|
||||
data, err := gamedata.GetData(CFG_PLAYROOM_SHOP)
|
||||
if err != nil {
|
||||
log.Debug("GetShopItemAdNum err:%v", err)
|
||||
return 0
|
||||
}
|
||||
for _, v := range data {
|
||||
if gamedata.GetIntValue(v, "ItemId") == Id {
|
||||
return gamedata.GetIntValue(v, "Dailystorage")
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func GetDecoInfo(Id int) (int, string) {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_PLAYROOM_DECORATE, Id)
|
||||
if err != nil {
|
||||
log.Debug("GetDecoInfo err:%v", err)
|
||||
return 0, ""
|
||||
}
|
||||
Type := gamedata.GetIntValue(data, "TypeEnum")
|
||||
Name := gamedata.GetStringValue(data, "Chinese")
|
||||
return Type, Name
|
||||
}
|
||||
|
||||
func GetDailyTaskListById(Id int) []int {
|
||||
data, err := gamedata.GetData(CFG_PLAYROOM_DAILYTASK)
|
||||
if err != nil {
|
||||
log.Debug("GetDailyTaskListById err:%v", err)
|
||||
return nil
|
||||
}
|
||||
Type := GetDailyTaskType(Id)
|
||||
r := make([]int, 0, len(data))
|
||||
for k, v := range data {
|
||||
if gamedata.GetIntValue(v, "Type") == Type {
|
||||
r = append(r, GoUtil.Int(k))
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func GetItemAddPhysiology(Item map[int]int) int {
|
||||
r := 0
|
||||
data, err := gamedata.GetData(CFG_PLAYROOM_MOOD)
|
||||
if err != nil {
|
||||
log.Debug("GetItemAddPhysiology err")
|
||||
return 0
|
||||
}
|
||||
for _, v := range data {
|
||||
costItem := gamedata.GetItemList(v, "Cost2")
|
||||
if len(costItem) < 1 {
|
||||
continue
|
||||
}
|
||||
if costItem[0].Id == 0 {
|
||||
continue
|
||||
}
|
||||
if val, ok := Item[costItem[0].Id]; ok {
|
||||
r += gamedata.GetIntValue(v, "PEffect") * val
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func GetPlayroomTaskDailyNum1() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_PLAYROOM_CONST, "dailytask_groupnum1")
|
||||
if err != nil {
|
||||
log.Debug("GetPlayroomTaskDailyNum1 err:%v", err)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
func GetPlayroomTaskDailyNum2() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_PLAYROOM_CONST, "dailytask_groupnum2")
|
||||
if err != nil {
|
||||
log.Debug("GetPlayroomTaskDailyNum2 err:%v", err)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
78
src/server/conf/race/race_cfg.go
Normal file
78
src/server/conf/race/race_cfg.go
Normal file
@ -0,0 +1,78 @@
|
||||
package raceCfg
|
||||
|
||||
import (
|
||||
"server/game/mod/item"
|
||||
"server/gamedata"
|
||||
)
|
||||
|
||||
const (
|
||||
CFG_RACE_TEMPLATE = "RaceTemplate"
|
||||
CFG_RACE_PASS = "RacePass"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gamedata.InitCfg(CFG_RACE_TEMPLATE)
|
||||
gamedata.InitCfg(CFG_RACE_PASS)
|
||||
}
|
||||
|
||||
func GetRaceNum(Pass int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_RACE_PASS, Pass)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Num")
|
||||
}
|
||||
|
||||
func GetRaceNeed(Pass int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_RACE_PASS, Pass)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Need")
|
||||
}
|
||||
|
||||
func GetMaxPass(Id int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_RACE_TEMPLATE, Id)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "PassNum")
|
||||
}
|
||||
func GetActivityItemId(Id int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_RACE_TEMPLATE, Id)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "ItemId")
|
||||
}
|
||||
func GetCD(Id int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_RACE_PASS, Id)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Cd")
|
||||
}
|
||||
|
||||
func GetCoin(Id int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_RACE_TEMPLATE, Id)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "ItemId")
|
||||
}
|
||||
|
||||
func GetExtraReward(Id int) []*item.Item {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_RACE_PASS, Id)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return gamedata.GetItemList(data, "ExtraReward")
|
||||
}
|
||||
|
||||
func GetReward(Id int) []*item.Item {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_RACE_PASS, Id)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return gamedata.GetItemList(data, "Reward")
|
||||
}
|
||||
52
src/server/conf/randname/randname_cfg.go
Normal file
52
src/server/conf/randname/randname_cfg.go
Normal file
@ -0,0 +1,52 @@
|
||||
package randnameCfg
|
||||
|
||||
import (
|
||||
GoUtil "server/game_util"
|
||||
"server/gamedata"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const (
|
||||
CFG_RAND_NAME = "RandName"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gamedata.InitCfg(CFG_RAND_NAME)
|
||||
}
|
||||
|
||||
func GetRandName() string {
|
||||
data, _ := gamedata.GetData(CFG_RAND_NAME)
|
||||
Id := GoUtil.RandNum(1, len(data))
|
||||
v, err := gamedata.GetDataByIntKey(CFG_RAND_NAME, Id)
|
||||
if err != nil {
|
||||
return "Lily"
|
||||
}
|
||||
return gamedata.GetStringValue(v, "EnName")
|
||||
}
|
||||
|
||||
func GetRandNames(n int) []string {
|
||||
rs := make([]string, 0)
|
||||
data, err := gamedata.GetData(CFG_RAND_NAME)
|
||||
if err != nil {
|
||||
for i := 0; i < n; i++ {
|
||||
id := strconv.Itoa(i + 1)
|
||||
rs[i] = "Lily" + id
|
||||
}
|
||||
}
|
||||
all := make([]int, len(data))
|
||||
index := 0
|
||||
for k := range data {
|
||||
ik := GoUtil.Int(k)
|
||||
all[index] = ik
|
||||
index++
|
||||
}
|
||||
ids := GoUtil.RandSliceNumNonAdjacent(all, n)
|
||||
for _, v := range ids {
|
||||
v, err := gamedata.GetDataByIntKey(CFG_RAND_NAME, v)
|
||||
if err != nil {
|
||||
rs = append(rs, "Lucy")
|
||||
}
|
||||
rs = append(rs, gamedata.GetStringValue(v, "EnName"))
|
||||
}
|
||||
return rs
|
||||
}
|
||||
@ -1,32 +1,49 @@
|
||||
{
|
||||
"AppID": 0,
|
||||
"LogLevel": "debug",
|
||||
"LogPath": "",
|
||||
"TCPAddr": ":3565",
|
||||
"WSAddr": ":3566",
|
||||
"LogPath": "./log",
|
||||
"TCPAddr": ":3602",
|
||||
"WSAddr": ":3567",
|
||||
"RPCAddr": ":50051",
|
||||
"MySqlAddr": "127.0.0.1",
|
||||
"MySqlPort": "3306",
|
||||
"MySqlUsr": "root",
|
||||
"MySqlPwd": "root",
|
||||
"MySqlPwd": "IOagNEq3C84c-20CmHEin5iODVc=",
|
||||
"MaxConnNum": 20000,
|
||||
"DbName": "Merge_Pet",
|
||||
"DbName": "merge_pet_1",
|
||||
"HttpPort": ":8081",
|
||||
"RemoteAddr":"host.docker.internal:9001",
|
||||
"AppPath": "./app",
|
||||
"TELOGDIR" : "./log/teLog/",
|
||||
|
||||
"GameName": "pet_home_local",
|
||||
|
||||
"GameName": "Merge_Pet",
|
||||
"GameID": 1,
|
||||
"ServerType":"node",
|
||||
|
||||
"ServerID": 1,
|
||||
"ServerOpenTime": "2018-01-01 00:00:00",
|
||||
"ServerName": "Merge_Pet",
|
||||
"ServerStatus" : 1,
|
||||
"ServerCenter" : 1,
|
||||
"ServerCenter" : 0,
|
||||
"GameConfPath": "D:/Github/pet_home_server/src/server/gamedata/config/",
|
||||
|
||||
"ListenAddr":":9002",
|
||||
"CenterAddr": "127.0.0.1:7000",
|
||||
"RemoteAddr":"127.0.0.1:9002",
|
||||
|
||||
"RedisAddr":"127.0.0.1",
|
||||
"RedisPort" :"6379",
|
||||
"RedisAddr":"127.0.0.1",
|
||||
"RedisPort" :"6379",
|
||||
"RedisPwd" :"",
|
||||
|
||||
"ListenAddr": ":9001",
|
||||
"CenterAddr": ":3560"
|
||||
"RedisWriteAddr":"127.0.0.1:6379",
|
||||
"RedisReadAddrs":"127.0.0.1:6379",
|
||||
"RedisMasterName":"mymaster",
|
||||
"RedisConnType":"Direct",
|
||||
|
||||
"GoogleVerify":false,
|
||||
"Partition":3,
|
||||
"KafkaHost":"kafka-server",
|
||||
"CountryCode":"004",
|
||||
"KafkaPort":"9092",
|
||||
"Version":"1.0.0",
|
||||
"IdVerify":false
|
||||
}
|
||||
|
||||
@ -4,8 +4,9 @@ import (
|
||||
"math"
|
||||
"server/game/mod/item"
|
||||
"server/gamedata"
|
||||
"server/pkg/github.com/name5566/leaf/log"
|
||||
"strconv"
|
||||
|
||||
"gitea.bywaystudios.com/pet_home/leaf/log"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -29,18 +30,18 @@ func GetSevenLoginReward() []*gamedata.SevenLoginRewardData {
|
||||
var result []*gamedata.SevenLoginRewardData
|
||||
for k, v := range data {
|
||||
Id, _ := strconv.Atoi(k)
|
||||
Diamond := gamedata.GetIntValue(v, "Diamond")
|
||||
Energy := gamedata.GetFloatValue(v, "Energy")
|
||||
RewardNum := gamedata.GetIntValue(v, "RewardNum")
|
||||
result = append(result, &gamedata.SevenLoginRewardData{
|
||||
Id: Id,
|
||||
Diamond: Diamond,
|
||||
Energy: Energy,
|
||||
RewardNum: RewardNum,
|
||||
})
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func GetSevenLoginMonthReward() []*gamedata.SevenLoginRewardData {
|
||||
func GetSevenLoginMonthReward(nowMonth int) []*gamedata.SevenLoginRewardData {
|
||||
data, err := gamedata.GetData(CFG_SEVEN_LOGIN_MONTH)
|
||||
if err != nil {
|
||||
log.Debug("GetSevenLoginReward err:%v", err)
|
||||
@ -48,19 +49,23 @@ func GetSevenLoginMonthReward() []*gamedata.SevenLoginRewardData {
|
||||
}
|
||||
var result []*gamedata.SevenLoginRewardData
|
||||
for k, v := range data {
|
||||
month := gamedata.GetIntValue(v, "Month")
|
||||
if month != nowMonth {
|
||||
continue
|
||||
}
|
||||
Id, _ := strconv.Atoi(k)
|
||||
Diamond := gamedata.GetIntValue(v, "Diamond")
|
||||
Energy := gamedata.GetFloatValue(v, "Energy")
|
||||
RewardNum := gamedata.GetIntValue(v, "RewardNum")
|
||||
result = append(result, &gamedata.SevenLoginRewardData{
|
||||
Id: Id,
|
||||
Diamond: Diamond,
|
||||
Energy: Energy,
|
||||
RewardNum: RewardNum,
|
||||
})
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func GetSevenLoginJackpot(IsMonth int) []*gamedata.SevenLoginJackpotData {
|
||||
func GetSevenLoginJackpot(isMonth, level int) []*gamedata.SevenLoginJackpotData {
|
||||
data, err := gamedata.GetData(CFG_SEVEN_LOGIN_JACKPOT)
|
||||
if err != nil {
|
||||
log.Debug("GetSevenLoginJackpot err:%v", err)
|
||||
@ -69,20 +74,24 @@ func GetSevenLoginJackpot(IsMonth int) []*gamedata.SevenLoginJackpotData {
|
||||
var result []*gamedata.SevenLoginJackpotData
|
||||
for k, v := range data {
|
||||
Id, _ := strconv.Atoi(k)
|
||||
Diamond := gamedata.GetIntValue(v, "Diamond")
|
||||
Energy := gamedata.GetFloatValue(v, "Energy")
|
||||
Type := gamedata.GetIntValue(v, "Type")
|
||||
Month := gamedata.GetIntValue(v, "Month")
|
||||
if IsMonth != Month && IsMonth != 0 {
|
||||
Level := gamedata.GetIntValue(v, "Level")
|
||||
if isMonth != Month && isMonth != 0 {
|
||||
continue
|
||||
}
|
||||
if level < Level && level != 0 {
|
||||
continue
|
||||
}
|
||||
ItemMap := gamedata.GetValue(v, "Item")
|
||||
Items := item.ParseItem(ItemMap)
|
||||
result = append(result, &gamedata.SevenLoginJackpotData{
|
||||
Id: Id,
|
||||
Diamond: Diamond,
|
||||
Items: Items,
|
||||
Type: Type,
|
||||
Month: Month,
|
||||
Id: Id,
|
||||
Energy: Energy,
|
||||
Items: Items,
|
||||
Type: Type,
|
||||
Month: Month,
|
||||
})
|
||||
}
|
||||
return result
|
||||
@ -18,7 +18,7 @@ func GetStartChessList() []int {
|
||||
var ChessList []int
|
||||
for _, v := range data {
|
||||
v1 := v.(map[string]interface{})
|
||||
ChessList = append(ChessList, gamedata.ParseInt(v1["MergeId"]))
|
||||
ChessList = append(ChessList, gamedata.GetIntValue(v1, "MergeId"))
|
||||
}
|
||||
return ChessList
|
||||
}
|
||||
@ -1,85 +0,0 @@
|
||||
package userCfg
|
||||
|
||||
import (
|
||||
"server/game/mod/item"
|
||||
"server/gamedata"
|
||||
"server/pkg/github.com/name5566/leaf/log"
|
||||
)
|
||||
|
||||
var CFG_NAME = "UserData"
|
||||
|
||||
func init() {
|
||||
gamedata.InitCfg(CFG_NAME)
|
||||
}
|
||||
|
||||
// 获取用户能量倍数
|
||||
func GetEnergyMulByLv(lv int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, lv)
|
||||
if err != nil {
|
||||
log.Debug("UserDataCfg GetEnergyMulByLv lv:%v not found", lv)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "EnergyMul")
|
||||
}
|
||||
|
||||
// 获取七天登录加成
|
||||
func GetSevenloginAdd(Lv int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, Lv)
|
||||
if err != nil {
|
||||
log.Debug("UserDataCfg GetSevenloginAdd lv:%v not found", Lv)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "SevenLogin")
|
||||
}
|
||||
|
||||
// 获取订单系数
|
||||
func GetOrderNByLv(lv int) (int, error) {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, lv)
|
||||
if err != nil {
|
||||
log.Debug("UserDataCfg GetOrderNByLv lv:%v not found", lv)
|
||||
return 0, err
|
||||
}
|
||||
return gamedata.GetIntValue(data, "OrderN"), nil
|
||||
}
|
||||
|
||||
// 获取升级经验
|
||||
func GetLevUpExp(lv int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, lv)
|
||||
if err != nil {
|
||||
log.Debug("UserDataCfg GetLevUpExp lv:%v not found", lv)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Exp")
|
||||
}
|
||||
|
||||
// 获取能量回复时间
|
||||
func GetRecover(lv int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, lv)
|
||||
if err != nil {
|
||||
log.Debug("UserDataCfg GetRecover lv:%v not found", lv)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Recover")
|
||||
}
|
||||
|
||||
// 获取解锁背包数量
|
||||
func GetUnlockPack(lv int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, lv)
|
||||
if err != nil {
|
||||
log.Debug("UserDataCfg GetUnlockPack lv:%v not found", lv)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "UnlockPack")
|
||||
}
|
||||
|
||||
// 获取升级奖励
|
||||
func GetLevUpReward(lv int) []*item.Item {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, lv)
|
||||
if err != nil {
|
||||
log.Debug("UserDataCfg GetLevUpReward lv:%v not found", lv)
|
||||
return nil
|
||||
}
|
||||
itemMap := gamedata.GetValue(data, "Item")
|
||||
itemList := item.ParseItem(itemMap)
|
||||
return itemList
|
||||
}
|
||||
169
src/server/conf/user/user_cfg.go
Normal file
169
src/server/conf/user/user_cfg.go
Normal file
@ -0,0 +1,169 @@
|
||||
package userCfg
|
||||
|
||||
import (
|
||||
"server/game/mod/item"
|
||||
"server/gamedata"
|
||||
|
||||
"gitea.bywaystudios.com/pet_home/leaf/log"
|
||||
)
|
||||
|
||||
const (
|
||||
CFG_NAME = "UserData"
|
||||
CFG_NANE_CONST = "UserDataConst"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gamedata.InitCfg(CFG_NAME)
|
||||
gamedata.InitCfg(CFG_NANE_CONST)
|
||||
}
|
||||
|
||||
// 获取用户能量倍数
|
||||
func GetEnergyMulByLv(lv int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, lv)
|
||||
if err != nil {
|
||||
log.Debug("UserDataCfg GetEnergyMulByLv lv:%v not found", lv)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "EnergyMul")
|
||||
}
|
||||
|
||||
func GetEnergyMax(Lv int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, Lv)
|
||||
if err != nil {
|
||||
log.Debug("UserDataCfg GetEnergyMax lv:%v not found", Lv)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "MaxEnergy")
|
||||
}
|
||||
|
||||
// 获取七天登录加成
|
||||
func GetSevenloginAdd(Lv int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, Lv)
|
||||
if err != nil {
|
||||
log.Debug("UserDataCfg GetSevenloginAdd lv:%v not found", Lv)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "SevenLogin")
|
||||
}
|
||||
|
||||
// 获取订单系数
|
||||
func GetOrderNByLv(lv int) (int, error) {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, lv)
|
||||
if err != nil {
|
||||
log.Debug("UserDataCfg GetOrderNByLv lv:%v not found", lv)
|
||||
return 0, err
|
||||
}
|
||||
return gamedata.GetIntValue(data, "OrderN"), nil
|
||||
}
|
||||
|
||||
// 获取升级经验
|
||||
func GetLevUpExp(lv int) (int, int) {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, lv)
|
||||
if err != nil {
|
||||
log.Debug("UserDataCfg GetLevUpExp lv:%v not found", lv)
|
||||
return 0, 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Exp"), gamedata.GetIntValue(data, "PExp")
|
||||
}
|
||||
|
||||
func GetNewLevUpExp(lv int, Exp int, PetExt int) (int, int) {
|
||||
ExpLv := lv
|
||||
PetLv := lv
|
||||
for {
|
||||
data1, err := gamedata.GetDataByIntKey(CFG_NAME, ExpLv)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
ExpNeed := gamedata.GetIntValue(data1, "Exp")
|
||||
if Exp >= ExpNeed {
|
||||
Exp -= ExpNeed
|
||||
ExpLv++
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
for {
|
||||
data2, err := gamedata.GetDataByIntKey(CFG_NAME, PetLv)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
PetNeed := gamedata.GetIntValue(data2, "PExp")
|
||||
if PetExt >= PetNeed {
|
||||
PetExt -= PetNeed
|
||||
PetLv++
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
return ExpLv, PetLv
|
||||
}
|
||||
|
||||
// 获取能量回复时间
|
||||
func GetRecover(lv int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, lv)
|
||||
if err != nil {
|
||||
log.Debug("UserDataCfg GetRecover lv:%v not found", lv)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Recover")
|
||||
}
|
||||
|
||||
// 获取解锁背包数量
|
||||
func GetUnlockPack(lv int) int {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, lv)
|
||||
if err != nil {
|
||||
log.Debug("UserDataCfg GetUnlockPack lv:%v not found", lv)
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "UnlockPack")
|
||||
}
|
||||
|
||||
// 获取升级奖励
|
||||
func GetLevUpReward(lv int) []*item.Item {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, lv)
|
||||
if err != nil {
|
||||
log.Debug("UserDataCfg GetLevUpReward lv:%v not found", lv)
|
||||
return nil
|
||||
}
|
||||
itemMap := gamedata.GetValue(data, "Item")
|
||||
itemList := item.ParseItem(itemMap)
|
||||
return itemList
|
||||
}
|
||||
|
||||
func GetUnlock(Lv int) string {
|
||||
data, err := gamedata.GetDataByIntKey(CFG_NAME, Lv)
|
||||
if err != nil {
|
||||
log.Debug("UserDataCfg GetUnlock lv:%v not found", Lv)
|
||||
return ""
|
||||
}
|
||||
s1 := gamedata.GetStringValue(data, "Unlock_1")
|
||||
s2 := gamedata.GetStringValue(data, "Unlock_2")
|
||||
return s1 + "," + s2
|
||||
}
|
||||
|
||||
func GetInitEnergy() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_NANE_CONST, "Energy")
|
||||
if err != nil {
|
||||
log.Debug("UserDataCfg GetInitEnergy not found")
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
func GetInitDiamond() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_NANE_CONST, "Diamond")
|
||||
if err != nil {
|
||||
log.Debug("UserDataCfg GetInitDiamond not found")
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
|
||||
func GetInitStar() int {
|
||||
data, err := gamedata.GetDataByKey(CFG_NANE_CONST, "Star")
|
||||
if err != nil {
|
||||
log.Debug("UserDataCfg GetInitStar not found")
|
||||
return 0
|
||||
}
|
||||
return gamedata.GetIntValue(data, "Value")
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
Copyright (C) 2012 Rob Figueiredo
|
||||
All Rights Reserved.
|
||||
|
||||
MIT LICENSE
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@ -1,125 +0,0 @@
|
||||
[](http://godoc.org/github.com/robfig/cron)
|
||||
[](https://travis-ci.org/robfig/cron)
|
||||
|
||||
# cron
|
||||
|
||||
Cron V3 has been released!
|
||||
|
||||
To download the specific tagged release, run:
|
||||
|
||||
go get github.com/robfig/cron/v3@v3.0.0
|
||||
|
||||
Import it in your program as:
|
||||
|
||||
import "github.com/robfig/cron/v3"
|
||||
|
||||
It requires Go 1.11 or later due to usage of Go Modules.
|
||||
|
||||
Refer to the documentation here:
|
||||
http://godoc.org/github.com/robfig/cron
|
||||
|
||||
The rest of this document describes the the advances in v3 and a list of
|
||||
breaking changes for users that wish to upgrade from an earlier version.
|
||||
|
||||
## Upgrading to v3 (June 2019)
|
||||
|
||||
cron v3 is a major upgrade to the library that addresses all outstanding bugs,
|
||||
feature requests, and rough edges. It is based on a merge of master which
|
||||
contains various fixes to issues found over the years and the v2 branch which
|
||||
contains some backwards-incompatible features like the ability to remove cron
|
||||
jobs. In addition, v3 adds support for Go Modules, cleans up rough edges like
|
||||
the timezone support, and fixes a number of bugs.
|
||||
|
||||
New features:
|
||||
|
||||
- Support for Go modules. Callers must now import this library as
|
||||
`github.com/robfig/cron/v3`, instead of `gopkg.in/...`
|
||||
|
||||
- Fixed bugs:
|
||||
- 0f01e6b parser: fix combining of Dow and Dom (#70)
|
||||
- dbf3220 adjust times when rolling the clock forward to handle non-existent midnight (#157)
|
||||
- eeecf15 spec_test.go: ensure an error is returned on 0 increment (#144)
|
||||
- 70971dc cron.Entries(): update request for snapshot to include a reply channel (#97)
|
||||
- 1cba5e6 cron: fix: removing a job causes the next scheduled job to run too late (#206)
|
||||
|
||||
- Standard cron spec parsing by default (first field is "minute"), with an easy
|
||||
way to opt into the seconds field (quartz-compatible). Although, note that the
|
||||
year field (optional in Quartz) is not supported.
|
||||
|
||||
- Extensible, key/value logging via an interface that complies with
|
||||
the https://github.com/go-logr/logr project.
|
||||
|
||||
- The new Chain & JobWrapper types allow you to install "interceptors" to add
|
||||
cross-cutting behavior like the following:
|
||||
- Recover any panics from jobs
|
||||
- Delay a job's execution if the previous run hasn't completed yet
|
||||
- Skip a job's execution if the previous run hasn't completed yet
|
||||
- Log each job's invocations
|
||||
- Notification when jobs are completed
|
||||
|
||||
It is backwards incompatible with both v1 and v2. These updates are required:
|
||||
|
||||
- The v1 branch accepted an optional seconds field at the beginning of the cron
|
||||
spec. This is non-standard and has led to a lot of confusion. The new default
|
||||
parser conforms to the standard as described by [the Cron wikipedia page].
|
||||
|
||||
UPDATING: To retain the old behavior, construct your Cron with a custom
|
||||
parser:
|
||||
|
||||
// Seconds field, required
|
||||
cron.New(cron.WithSeconds())
|
||||
|
||||
// Seconds field, optional
|
||||
cron.New(
|
||||
cron.WithParser(
|
||||
cron.SecondOptional | cron.Hour | cron.Dom | cron.Month | cron.Dow | cron.Descriptor))
|
||||
|
||||
- The Cron type now accepts functional options on construction rather than the
|
||||
previous ad-hoc behavior modification mechanisms (setting a field, calling a setter).
|
||||
|
||||
UPDATING: Code that sets Cron.ErrorLogger or calls Cron.SetLocation must be
|
||||
updated to provide those values on construction.
|
||||
|
||||
- CRON_TZ is now the recommended way to specify the timezone of a single
|
||||
schedule, which is sanctioned by the specification. The legacy "TZ=" prefix
|
||||
will continue to be supported since it is unambiguous and easy to do so.
|
||||
|
||||
UPDATING: No update is required.
|
||||
|
||||
- By default, cron will no longer recover panics in jobs that it runs.
|
||||
Recovering can be surprising (see issue #192) and seems to be at odds with
|
||||
typical behavior of libraries. Relatedly, the `cron.WithPanicLogger` option
|
||||
has been removed to accommodate the more general JobWrapper type.
|
||||
|
||||
UPDATING: To opt into panic recovery and configure the panic logger:
|
||||
|
||||
cron.New(cron.WithChain(
|
||||
cron.Recover(logger), // or use cron.DefaultLogger
|
||||
))
|
||||
|
||||
- In adding support for https://github.com/go-logr/logr, `cron.WithVerboseLogger` was
|
||||
removed, since it is duplicative with the leveled logging.
|
||||
|
||||
UPDATING: Callers should use `WithLogger` and specify a logger that does not
|
||||
discard `Info` logs. For convenience, one is provided that wraps `*log.Logger`:
|
||||
|
||||
cron.New(
|
||||
cron.WithLogger(cron.VerbosePrintfLogger(logger)))
|
||||
|
||||
|
||||
### Background - Cron spec format
|
||||
|
||||
There are two cron spec formats in common usage:
|
||||
|
||||
- The "standard" cron format, described on [the Cron wikipedia page] and used by
|
||||
the cron Linux system utility.
|
||||
|
||||
- The cron format used by [the Quartz Scheduler], commonly used for scheduled
|
||||
jobs in Java software
|
||||
|
||||
[the Cron wikipedia page]: https://en.wikipedia.org/wiki/Cron
|
||||
[the Quartz Scheduler]: http://www.quartz-scheduler.org/documentation/quartz-2.x/tutorials/crontrigger.html
|
||||
|
||||
The original version of this package included an optional "seconds" field, which
|
||||
made it incompatible with both of these formats. Now, the "standard" format is
|
||||
the default format accepted, and the Quartz format is opt-in.
|
||||
@ -1,92 +0,0 @@
|
||||
package cron
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// JobWrapper decorates the given Job with some behavior.
|
||||
type JobWrapper func(Job) Job
|
||||
|
||||
// Chain is a sequence of JobWrappers that decorates submitted jobs with
|
||||
// cross-cutting behaviors like logging or synchronization.
|
||||
type Chain struct {
|
||||
wrappers []JobWrapper
|
||||
}
|
||||
|
||||
// NewChain returns a Chain consisting of the given JobWrappers.
|
||||
func NewChain(c ...JobWrapper) Chain {
|
||||
return Chain{c}
|
||||
}
|
||||
|
||||
// Then decorates the given job with all JobWrappers in the chain.
|
||||
//
|
||||
// This:
|
||||
// NewChain(m1, m2, m3).Then(job)
|
||||
// is equivalent to:
|
||||
// m1(m2(m3(job)))
|
||||
func (c Chain) Then(j Job) Job {
|
||||
for i := range c.wrappers {
|
||||
j = c.wrappers[len(c.wrappers)-i-1](j)
|
||||
}
|
||||
return j
|
||||
}
|
||||
|
||||
// Recover panics in wrapped jobs and log them with the provided logger.
|
||||
func Recover(logger Logger) JobWrapper {
|
||||
return func(j Job) Job {
|
||||
return FuncJob(func() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
const size = 64 << 10
|
||||
buf := make([]byte, size)
|
||||
buf = buf[:runtime.Stack(buf, false)]
|
||||
err, ok := r.(error)
|
||||
if !ok {
|
||||
err = fmt.Errorf("%v", r)
|
||||
}
|
||||
logger.Error(err, "panic", "stack", "...\n"+string(buf))
|
||||
}
|
||||
}()
|
||||
j.Run()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// DelayIfStillRunning serializes jobs, delaying subsequent runs until the
|
||||
// previous one is complete. Jobs running after a delay of more than a minute
|
||||
// have the delay logged at Info.
|
||||
func DelayIfStillRunning(logger Logger) JobWrapper {
|
||||
return func(j Job) Job {
|
||||
var mu sync.Mutex
|
||||
return FuncJob(func() {
|
||||
start := time.Now()
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
if dur := time.Since(start); dur > time.Minute {
|
||||
logger.Info("delay", "duration", dur)
|
||||
}
|
||||
j.Run()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// SkipIfStillRunning skips an invocation of the Job if a previous invocation is
|
||||
// still running. It logs skips to the given logger at Info level.
|
||||
func SkipIfStillRunning(logger Logger) JobWrapper {
|
||||
var ch = make(chan struct{}, 1)
|
||||
ch <- struct{}{}
|
||||
return func(j Job) Job {
|
||||
return FuncJob(func() {
|
||||
select {
|
||||
case v := <-ch:
|
||||
j.Run()
|
||||
ch <- v
|
||||
default:
|
||||
logger.Info("skip")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -1,221 +0,0 @@
|
||||
package cron
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"reflect"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func appendingJob(slice *[]int, value int) Job {
|
||||
var m sync.Mutex
|
||||
return FuncJob(func() {
|
||||
m.Lock()
|
||||
*slice = append(*slice, value)
|
||||
m.Unlock()
|
||||
})
|
||||
}
|
||||
|
||||
func appendingWrapper(slice *[]int, value int) JobWrapper {
|
||||
return func(j Job) Job {
|
||||
return FuncJob(func() {
|
||||
appendingJob(slice, value).Run()
|
||||
j.Run()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestChain(t *testing.T) {
|
||||
var nums []int
|
||||
var (
|
||||
append1 = appendingWrapper(&nums, 1)
|
||||
append2 = appendingWrapper(&nums, 2)
|
||||
append3 = appendingWrapper(&nums, 3)
|
||||
append4 = appendingJob(&nums, 4)
|
||||
)
|
||||
NewChain(append1, append2, append3).Then(append4).Run()
|
||||
if !reflect.DeepEqual(nums, []int{1, 2, 3, 4}) {
|
||||
t.Error("unexpected order of calls:", nums)
|
||||
}
|
||||
}
|
||||
|
||||
func TestChainRecover(t *testing.T) {
|
||||
panickingJob := FuncJob(func() {
|
||||
panic("panickingJob panics")
|
||||
})
|
||||
|
||||
t.Run("panic exits job by default", func(t *testing.T) {
|
||||
defer func() {
|
||||
if err := recover(); err == nil {
|
||||
t.Errorf("panic expected, but none received")
|
||||
}
|
||||
}()
|
||||
NewChain().Then(panickingJob).
|
||||
Run()
|
||||
})
|
||||
|
||||
t.Run("Recovering JobWrapper recovers", func(t *testing.T) {
|
||||
NewChain(Recover(PrintfLogger(log.New(ioutil.Discard, "", 0)))).
|
||||
Then(panickingJob).
|
||||
Run()
|
||||
})
|
||||
|
||||
t.Run("composed with the *IfStillRunning wrappers", func(t *testing.T) {
|
||||
NewChain(Recover(PrintfLogger(log.New(ioutil.Discard, "", 0)))).
|
||||
Then(panickingJob).
|
||||
Run()
|
||||
})
|
||||
}
|
||||
|
||||
type countJob struct {
|
||||
m sync.Mutex
|
||||
started int
|
||||
done int
|
||||
delay time.Duration
|
||||
}
|
||||
|
||||
func (j *countJob) Run() {
|
||||
j.m.Lock()
|
||||
j.started++
|
||||
j.m.Unlock()
|
||||
time.Sleep(j.delay)
|
||||
j.m.Lock()
|
||||
j.done++
|
||||
j.m.Unlock()
|
||||
}
|
||||
|
||||
func (j *countJob) Started() int {
|
||||
defer j.m.Unlock()
|
||||
j.m.Lock()
|
||||
return j.started
|
||||
}
|
||||
|
||||
func (j *countJob) Done() int {
|
||||
defer j.m.Unlock()
|
||||
j.m.Lock()
|
||||
return j.done
|
||||
}
|
||||
|
||||
func TestChainDelayIfStillRunning(t *testing.T) {
|
||||
|
||||
t.Run("runs immediately", func(t *testing.T) {
|
||||
var j countJob
|
||||
wrappedJob := NewChain(DelayIfStillRunning(DiscardLogger)).Then(&j)
|
||||
go wrappedJob.Run()
|
||||
time.Sleep(2 * time.Millisecond) // Give the job 2ms to complete.
|
||||
if c := j.Done(); c != 1 {
|
||||
t.Errorf("expected job run once, immediately, got %d", c)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("second run immediate if first done", func(t *testing.T) {
|
||||
var j countJob
|
||||
wrappedJob := NewChain(DelayIfStillRunning(DiscardLogger)).Then(&j)
|
||||
go func() {
|
||||
go wrappedJob.Run()
|
||||
time.Sleep(time.Millisecond)
|
||||
go wrappedJob.Run()
|
||||
}()
|
||||
time.Sleep(3 * time.Millisecond) // Give both jobs 3ms to complete.
|
||||
if c := j.Done(); c != 2 {
|
||||
t.Errorf("expected job run twice, immediately, got %d", c)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("second run delayed if first not done", func(t *testing.T) {
|
||||
var j countJob
|
||||
j.delay = 10 * time.Millisecond
|
||||
wrappedJob := NewChain(DelayIfStillRunning(DiscardLogger)).Then(&j)
|
||||
go func() {
|
||||
go wrappedJob.Run()
|
||||
time.Sleep(time.Millisecond)
|
||||
go wrappedJob.Run()
|
||||
}()
|
||||
|
||||
// After 5ms, the first job is still in progress, and the second job was
|
||||
// run but should be waiting for it to finish.
|
||||
time.Sleep(5 * time.Millisecond)
|
||||
started, done := j.Started(), j.Done()
|
||||
if started != 1 || done != 0 {
|
||||
t.Error("expected first job started, but not finished, got", started, done)
|
||||
}
|
||||
|
||||
// Verify that the second job completes.
|
||||
time.Sleep(25 * time.Millisecond)
|
||||
started, done = j.Started(), j.Done()
|
||||
if started != 2 || done != 2 {
|
||||
t.Error("expected both jobs done, got", started, done)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func TestChainSkipIfStillRunning(t *testing.T) {
|
||||
|
||||
t.Run("runs immediately", func(t *testing.T) {
|
||||
var j countJob
|
||||
wrappedJob := NewChain(SkipIfStillRunning(DiscardLogger)).Then(&j)
|
||||
go wrappedJob.Run()
|
||||
time.Sleep(2 * time.Millisecond) // Give the job 2ms to complete.
|
||||
if c := j.Done(); c != 1 {
|
||||
t.Errorf("expected job run once, immediately, got %d", c)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("second run immediate if first done", func(t *testing.T) {
|
||||
var j countJob
|
||||
wrappedJob := NewChain(SkipIfStillRunning(DiscardLogger)).Then(&j)
|
||||
go func() {
|
||||
go wrappedJob.Run()
|
||||
time.Sleep(time.Millisecond)
|
||||
go wrappedJob.Run()
|
||||
}()
|
||||
time.Sleep(3 * time.Millisecond) // Give both jobs 3ms to complete.
|
||||
if c := j.Done(); c != 2 {
|
||||
t.Errorf("expected job run twice, immediately, got %d", c)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("second run skipped if first not done", func(t *testing.T) {
|
||||
var j countJob
|
||||
j.delay = 10 * time.Millisecond
|
||||
wrappedJob := NewChain(SkipIfStillRunning(DiscardLogger)).Then(&j)
|
||||
go func() {
|
||||
go wrappedJob.Run()
|
||||
time.Sleep(time.Millisecond)
|
||||
go wrappedJob.Run()
|
||||
}()
|
||||
|
||||
// After 5ms, the first job is still in progress, and the second job was
|
||||
// aleady skipped.
|
||||
time.Sleep(5 * time.Millisecond)
|
||||
started, done := j.Started(), j.Done()
|
||||
if started != 1 || done != 0 {
|
||||
t.Error("expected first job started, but not finished, got", started, done)
|
||||
}
|
||||
|
||||
// Verify that the first job completes and second does not run.
|
||||
time.Sleep(25 * time.Millisecond)
|
||||
started, done = j.Started(), j.Done()
|
||||
if started != 1 || done != 1 {
|
||||
t.Error("expected second job skipped, got", started, done)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("skip 10 jobs on rapid fire", func(t *testing.T) {
|
||||
var j countJob
|
||||
j.delay = 10 * time.Millisecond
|
||||
wrappedJob := NewChain(SkipIfStillRunning(DiscardLogger)).Then(&j)
|
||||
for i := 0; i < 11; i++ {
|
||||
go wrappedJob.Run()
|
||||
}
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
done := j.Done()
|
||||
if done != 1 {
|
||||
t.Error("expected 1 jobs executed, 10 jobs dropped, got", done)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
@ -1,27 +0,0 @@
|
||||
package cron
|
||||
|
||||
import "time"
|
||||
|
||||
// ConstantDelaySchedule represents a simple recurring duty cycle, e.g. "Every 5 minutes".
|
||||
// It does not support jobs more frequent than once a second.
|
||||
type ConstantDelaySchedule struct {
|
||||
Delay time.Duration
|
||||
}
|
||||
|
||||
// Every returns a crontab Schedule that activates once every duration.
|
||||
// Delays of less than a second are not supported (will round up to 1 second).
|
||||
// Any fields less than a Second are truncated.
|
||||
func Every(duration time.Duration) ConstantDelaySchedule {
|
||||
if duration < time.Second {
|
||||
duration = time.Second
|
||||
}
|
||||
return ConstantDelaySchedule{
|
||||
Delay: duration - time.Duration(duration.Nanoseconds())%time.Second,
|
||||
}
|
||||
}
|
||||
|
||||
// Next returns the next time this should be run.
|
||||
// This rounds so that the next activation time will be on the second.
|
||||
func (schedule ConstantDelaySchedule) Next(t time.Time) time.Time {
|
||||
return t.Add(schedule.Delay - time.Duration(t.Nanosecond())*time.Nanosecond)
|
||||
}
|
||||
@ -1,54 +0,0 @@
|
||||
package cron
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestConstantDelayNext(t *testing.T) {
|
||||
tests := []struct {
|
||||
time string
|
||||
delay time.Duration
|
||||
expected string
|
||||
}{
|
||||
// Simple cases
|
||||
{"Mon Jul 9 14:45 2012", 15*time.Minute + 50*time.Nanosecond, "Mon Jul 9 15:00 2012"},
|
||||
{"Mon Jul 9 14:59 2012", 15 * time.Minute, "Mon Jul 9 15:14 2012"},
|
||||
{"Mon Jul 9 14:59:59 2012", 15 * time.Minute, "Mon Jul 9 15:14:59 2012"},
|
||||
|
||||
// Wrap around hours
|
||||
{"Mon Jul 9 15:45 2012", 35 * time.Minute, "Mon Jul 9 16:20 2012"},
|
||||
|
||||
// Wrap around days
|
||||
{"Mon Jul 9 23:46 2012", 14 * time.Minute, "Tue Jul 10 00:00 2012"},
|
||||
{"Mon Jul 9 23:45 2012", 35 * time.Minute, "Tue Jul 10 00:20 2012"},
|
||||
{"Mon Jul 9 23:35:51 2012", 44*time.Minute + 24*time.Second, "Tue Jul 10 00:20:15 2012"},
|
||||
{"Mon Jul 9 23:35:51 2012", 25*time.Hour + 44*time.Minute + 24*time.Second, "Thu Jul 11 01:20:15 2012"},
|
||||
|
||||
// Wrap around months
|
||||
{"Mon Jul 9 23:35 2012", 91*24*time.Hour + 25*time.Minute, "Thu Oct 9 00:00 2012"},
|
||||
|
||||
// Wrap around minute, hour, day, month, and year
|
||||
{"Mon Dec 31 23:59:45 2012", 15 * time.Second, "Tue Jan 1 00:00:00 2013"},
|
||||
|
||||
// Round to nearest second on the delay
|
||||
{"Mon Jul 9 14:45 2012", 15*time.Minute + 50*time.Nanosecond, "Mon Jul 9 15:00 2012"},
|
||||
|
||||
// Round up to 1 second if the duration is less.
|
||||
{"Mon Jul 9 14:45:00 2012", 15 * time.Millisecond, "Mon Jul 9 14:45:01 2012"},
|
||||
|
||||
// Round to nearest second when calculating the next time.
|
||||
{"Mon Jul 9 14:45:00.005 2012", 15 * time.Minute, "Mon Jul 9 15:00 2012"},
|
||||
|
||||
// Round to nearest second for both.
|
||||
{"Mon Jul 9 14:45:00.005 2012", 15*time.Minute + 50*time.Nanosecond, "Mon Jul 9 15:00 2012"},
|
||||
}
|
||||
|
||||
for _, c := range tests {
|
||||
actual := Every(c.delay).Next(getTime(c.time))
|
||||
expected := getTime(c.expected)
|
||||
if actual != expected {
|
||||
t.Errorf("%s, \"%s\": (expected) %v != %v (actual)", c.time, c.delay, expected, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,350 +0,0 @@
|
||||
package cron
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sort"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Cron keeps track of any number of entries, invoking the associated func as
|
||||
// specified by the schedule. It may be started, stopped, and the entries may
|
||||
// be inspected while running.
|
||||
type Cron struct {
|
||||
entries []*Entry
|
||||
chain Chain
|
||||
stop chan struct{}
|
||||
add chan *Entry
|
||||
remove chan EntryID
|
||||
snapshot chan chan []Entry
|
||||
running bool
|
||||
logger Logger
|
||||
runningMu sync.Mutex
|
||||
location *time.Location
|
||||
parser Parser
|
||||
nextID EntryID
|
||||
jobWaiter sync.WaitGroup
|
||||
}
|
||||
|
||||
// Job is an interface for submitted cron jobs.
|
||||
type Job interface {
|
||||
Run()
|
||||
}
|
||||
|
||||
// Schedule describes a job's duty cycle.
|
||||
type Schedule interface {
|
||||
// Next returns the next activation time, later than the given time.
|
||||
// Next is invoked initially, and then each time the job is run.
|
||||
Next(time.Time) time.Time
|
||||
}
|
||||
|
||||
// EntryID identifies an entry within a Cron instance
|
||||
type EntryID int
|
||||
|
||||
// Entry consists of a schedule and the func to execute on that schedule.
|
||||
type Entry struct {
|
||||
// ID is the cron-assigned ID of this entry, which may be used to look up a
|
||||
// snapshot or remove it.
|
||||
ID EntryID
|
||||
|
||||
// Schedule on which this job should be run.
|
||||
Schedule Schedule
|
||||
|
||||
// Next time the job will run, or the zero time if Cron has not been
|
||||
// started or this entry's schedule is unsatisfiable
|
||||
Next time.Time
|
||||
|
||||
// Prev is the last time this job was run, or the zero time if never.
|
||||
Prev time.Time
|
||||
|
||||
// WrappedJob is the thing to run when the Schedule is activated.
|
||||
WrappedJob Job
|
||||
|
||||
// Job is the thing that was submitted to cron.
|
||||
// It is kept around so that user code that needs to get at the job later,
|
||||
// e.g. via Entries() can do so.
|
||||
Job Job
|
||||
}
|
||||
|
||||
// Valid returns true if this is not the zero entry.
|
||||
func (e Entry) Valid() bool { return e.ID != 0 }
|
||||
|
||||
// byTime is a wrapper for sorting the entry array by time
|
||||
// (with zero time at the end).
|
||||
type byTime []*Entry
|
||||
|
||||
func (s byTime) Len() int { return len(s) }
|
||||
func (s byTime) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||
func (s byTime) Less(i, j int) bool {
|
||||
// Two zero times should return false.
|
||||
// Otherwise, zero is "greater" than any other time.
|
||||
// (To sort it at the end of the list.)
|
||||
if s[i].Next.IsZero() {
|
||||
return false
|
||||
}
|
||||
if s[j].Next.IsZero() {
|
||||
return true
|
||||
}
|
||||
return s[i].Next.Before(s[j].Next)
|
||||
}
|
||||
|
||||
// New returns a new Cron job runner, modified by the given options.
|
||||
//
|
||||
// Available Settings
|
||||
//
|
||||
// Time Zone
|
||||
// Description: The time zone in which schedules are interpreted
|
||||
// Default: time.Local
|
||||
//
|
||||
// Parser
|
||||
// Description: Parser converts cron spec strings into cron.Schedules.
|
||||
// Default: Accepts this spec: https://en.wikipedia.org/wiki/Cron
|
||||
//
|
||||
// Chain
|
||||
// Description: Wrap submitted jobs to customize behavior.
|
||||
// Default: A chain that recovers panics and logs them to stderr.
|
||||
//
|
||||
// See "cron.With*" to modify the default behavior.
|
||||
func New(opts ...Option) *Cron {
|
||||
c := &Cron{
|
||||
entries: nil,
|
||||
chain: NewChain(),
|
||||
add: make(chan *Entry),
|
||||
stop: make(chan struct{}),
|
||||
snapshot: make(chan chan []Entry),
|
||||
remove: make(chan EntryID),
|
||||
running: false,
|
||||
runningMu: sync.Mutex{},
|
||||
logger: DefaultLogger,
|
||||
location: time.Local,
|
||||
parser: standardParser,
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(c)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// FuncJob is a wrapper that turns a func() into a cron.Job
|
||||
type FuncJob func()
|
||||
|
||||
func (f FuncJob) Run() { f() }
|
||||
|
||||
// AddFunc adds a func to the Cron to be run on the given schedule.
|
||||
// The spec is parsed using the time zone of this Cron instance as the default.
|
||||
// An opaque ID is returned that can be used to later remove it.
|
||||
func (c *Cron) AddFunc(spec string, cmd func()) (EntryID, error) {
|
||||
return c.AddJob(spec, FuncJob(cmd))
|
||||
}
|
||||
|
||||
// AddJob adds a Job to the Cron to be run on the given schedule.
|
||||
// The spec is parsed using the time zone of this Cron instance as the default.
|
||||
// An opaque ID is returned that can be used to later remove it.
|
||||
func (c *Cron) AddJob(spec string, cmd Job) (EntryID, error) {
|
||||
schedule, err := c.parser.Parse(spec)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return c.Schedule(schedule, cmd), nil
|
||||
}
|
||||
|
||||
// Schedule adds a Job to the Cron to be run on the given schedule.
|
||||
// The job is wrapped with the configured Chain.
|
||||
func (c *Cron) Schedule(schedule Schedule, cmd Job) EntryID {
|
||||
c.runningMu.Lock()
|
||||
defer c.runningMu.Unlock()
|
||||
c.nextID++
|
||||
entry := &Entry{
|
||||
ID: c.nextID,
|
||||
Schedule: schedule,
|
||||
WrappedJob: c.chain.Then(cmd),
|
||||
Job: cmd,
|
||||
}
|
||||
if !c.running {
|
||||
c.entries = append(c.entries, entry)
|
||||
} else {
|
||||
c.add <- entry
|
||||
}
|
||||
return entry.ID
|
||||
}
|
||||
|
||||
// Entries returns a snapshot of the cron entries.
|
||||
func (c *Cron) Entries() []Entry {
|
||||
c.runningMu.Lock()
|
||||
defer c.runningMu.Unlock()
|
||||
if c.running {
|
||||
replyChan := make(chan []Entry, 1)
|
||||
c.snapshot <- replyChan
|
||||
return <-replyChan
|
||||
}
|
||||
return c.entrySnapshot()
|
||||
}
|
||||
|
||||
// Location gets the time zone location
|
||||
func (c *Cron) Location() *time.Location {
|
||||
return c.location
|
||||
}
|
||||
|
||||
// Entry returns a snapshot of the given entry, or nil if it couldn't be found.
|
||||
func (c *Cron) Entry(id EntryID) Entry {
|
||||
for _, entry := range c.Entries() {
|
||||
if id == entry.ID {
|
||||
return entry
|
||||
}
|
||||
}
|
||||
return Entry{}
|
||||
}
|
||||
|
||||
// Remove an entry from being run in the future.
|
||||
func (c *Cron) Remove(id EntryID) {
|
||||
c.runningMu.Lock()
|
||||
defer c.runningMu.Unlock()
|
||||
if c.running {
|
||||
c.remove <- id
|
||||
} else {
|
||||
c.removeEntry(id)
|
||||
}
|
||||
}
|
||||
|
||||
// Start the cron scheduler in its own goroutine, or no-op if already started.
|
||||
func (c *Cron) Start() {
|
||||
c.runningMu.Lock()
|
||||
defer c.runningMu.Unlock()
|
||||
if c.running {
|
||||
return
|
||||
}
|
||||
c.running = true
|
||||
go c.run()
|
||||
}
|
||||
|
||||
// Run the cron scheduler, or no-op if already running.
|
||||
func (c *Cron) Run() {
|
||||
c.runningMu.Lock()
|
||||
if c.running {
|
||||
c.runningMu.Unlock()
|
||||
return
|
||||
}
|
||||
c.running = true
|
||||
c.runningMu.Unlock()
|
||||
c.run()
|
||||
}
|
||||
|
||||
// run the scheduler.. this is private just due to the need to synchronize
|
||||
// access to the 'running' state variable.
|
||||
func (c *Cron) run() {
|
||||
c.logger.Info("start")
|
||||
|
||||
// Figure out the next activation times for each entry.
|
||||
now := c.now()
|
||||
for _, entry := range c.entries {
|
||||
entry.Next = entry.Schedule.Next(now)
|
||||
c.logger.Info("schedule", "now", now, "entry", entry.ID, "next", entry.Next)
|
||||
}
|
||||
|
||||
for {
|
||||
// Determine the next entry to run.
|
||||
sort.Sort(byTime(c.entries))
|
||||
|
||||
var timer *time.Timer
|
||||
if len(c.entries) == 0 || c.entries[0].Next.IsZero() {
|
||||
// If there are no entries yet, just sleep - it still handles new entries
|
||||
// and stop requests.
|
||||
timer = time.NewTimer(100000 * time.Hour)
|
||||
} else {
|
||||
timer = time.NewTimer(c.entries[0].Next.Sub(now))
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case now = <-timer.C:
|
||||
now = now.In(c.location)
|
||||
c.logger.Info("wake", "now", now)
|
||||
|
||||
// Run every entry whose next time was less than now
|
||||
for _, e := range c.entries {
|
||||
if e.Next.After(now) || e.Next.IsZero() {
|
||||
break
|
||||
}
|
||||
c.startJob(e.WrappedJob)
|
||||
e.Prev = e.Next
|
||||
e.Next = e.Schedule.Next(now)
|
||||
c.logger.Info("run", "now", now, "entry", e.ID, "next", e.Next)
|
||||
}
|
||||
|
||||
case newEntry := <-c.add:
|
||||
timer.Stop()
|
||||
now = c.now()
|
||||
newEntry.Next = newEntry.Schedule.Next(now)
|
||||
c.entries = append(c.entries, newEntry)
|
||||
c.logger.Info("added", "now", now, "entry", newEntry.ID, "next", newEntry.Next)
|
||||
|
||||
case replyChan := <-c.snapshot:
|
||||
replyChan <- c.entrySnapshot()
|
||||
continue
|
||||
|
||||
case <-c.stop:
|
||||
timer.Stop()
|
||||
c.logger.Info("stop")
|
||||
return
|
||||
|
||||
case id := <-c.remove:
|
||||
timer.Stop()
|
||||
now = c.now()
|
||||
c.removeEntry(id)
|
||||
c.logger.Info("removed", "entry", id)
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// startJob runs the given job in a new goroutine.
|
||||
func (c *Cron) startJob(j Job) {
|
||||
c.jobWaiter.Add(1)
|
||||
go func() {
|
||||
defer c.jobWaiter.Done()
|
||||
j.Run()
|
||||
}()
|
||||
}
|
||||
|
||||
// now returns current time in c location
|
||||
func (c *Cron) now() time.Time {
|
||||
return time.Now().In(c.location)
|
||||
}
|
||||
|
||||
// Stop stops the cron scheduler if it is running; otherwise it does nothing.
|
||||
// A context is returned so the caller can wait for running jobs to complete.
|
||||
func (c *Cron) Stop() context.Context {
|
||||
c.runningMu.Lock()
|
||||
defer c.runningMu.Unlock()
|
||||
if c.running {
|
||||
c.stop <- struct{}{}
|
||||
c.running = false
|
||||
}
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
go func() {
|
||||
c.jobWaiter.Wait()
|
||||
cancel()
|
||||
}()
|
||||
return ctx
|
||||
}
|
||||
|
||||
// entrySnapshot returns a copy of the current cron entry list.
|
||||
func (c *Cron) entrySnapshot() []Entry {
|
||||
var entries = make([]Entry, len(c.entries))
|
||||
for i, e := range c.entries {
|
||||
entries[i] = *e
|
||||
}
|
||||
return entries
|
||||
}
|
||||
|
||||
func (c *Cron) removeEntry(id EntryID) {
|
||||
var entries []*Entry
|
||||
for _, e := range c.entries {
|
||||
if e.ID != id {
|
||||
entries = append(entries, e)
|
||||
}
|
||||
}
|
||||
c.entries = entries
|
||||
}
|
||||
@ -1,702 +0,0 @@
|
||||
package cron
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Many tests schedule a job for every second, and then wait at most a second
|
||||
// for it to run. This amount is just slightly larger than 1 second to
|
||||
// compensate for a few milliseconds of runtime.
|
||||
const OneSecond = 1*time.Second + 50*time.Millisecond
|
||||
|
||||
type syncWriter struct {
|
||||
wr bytes.Buffer
|
||||
m sync.Mutex
|
||||
}
|
||||
|
||||
func (sw *syncWriter) Write(data []byte) (n int, err error) {
|
||||
sw.m.Lock()
|
||||
n, err = sw.wr.Write(data)
|
||||
sw.m.Unlock()
|
||||
return
|
||||
}
|
||||
|
||||
func (sw *syncWriter) String() string {
|
||||
sw.m.Lock()
|
||||
defer sw.m.Unlock()
|
||||
return sw.wr.String()
|
||||
}
|
||||
|
||||
func newBufLogger(sw *syncWriter) Logger {
|
||||
return PrintfLogger(log.New(sw, "", log.LstdFlags))
|
||||
}
|
||||
|
||||
func TestFuncPanicRecovery(t *testing.T) {
|
||||
var buf syncWriter
|
||||
cron := New(WithParser(secondParser),
|
||||
WithChain(Recover(newBufLogger(&buf))))
|
||||
cron.Start()
|
||||
defer cron.Stop()
|
||||
cron.AddFunc("* * * * * ?", func() {
|
||||
panic("YOLO")
|
||||
})
|
||||
|
||||
select {
|
||||
case <-time.After(OneSecond):
|
||||
if !strings.Contains(buf.String(), "YOLO") {
|
||||
t.Error("expected a panic to be logged, got none")
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
type DummyJob struct{}
|
||||
|
||||
func (d DummyJob) Run() {
|
||||
panic("YOLO")
|
||||
}
|
||||
|
||||
func TestJobPanicRecovery(t *testing.T) {
|
||||
var job DummyJob
|
||||
|
||||
var buf syncWriter
|
||||
cron := New(WithParser(secondParser),
|
||||
WithChain(Recover(newBufLogger(&buf))))
|
||||
cron.Start()
|
||||
defer cron.Stop()
|
||||
cron.AddJob("* * * * * ?", job)
|
||||
|
||||
select {
|
||||
case <-time.After(OneSecond):
|
||||
if !strings.Contains(buf.String(), "YOLO") {
|
||||
t.Error("expected a panic to be logged, got none")
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Start and stop cron with no entries.
|
||||
func TestNoEntries(t *testing.T) {
|
||||
cron := newWithSeconds()
|
||||
cron.Start()
|
||||
|
||||
select {
|
||||
case <-time.After(OneSecond):
|
||||
t.Fatal("expected cron will be stopped immediately")
|
||||
case <-stop(cron):
|
||||
}
|
||||
}
|
||||
|
||||
// Start, stop, then add an entry. Verify entry doesn't run.
|
||||
func TestStopCausesJobsToNotRun(t *testing.T) {
|
||||
wg := &sync.WaitGroup{}
|
||||
wg.Add(1)
|
||||
|
||||
cron := newWithSeconds()
|
||||
cron.Start()
|
||||
cron.Stop()
|
||||
cron.AddFunc("* * * * * ?", func() { wg.Done() })
|
||||
|
||||
select {
|
||||
case <-time.After(OneSecond):
|
||||
// No job ran!
|
||||
case <-wait(wg):
|
||||
t.Fatal("expected stopped cron does not run any job")
|
||||
}
|
||||
}
|
||||
|
||||
// Add a job, start cron, expect it runs.
|
||||
func TestAddBeforeRunning(t *testing.T) {
|
||||
wg := &sync.WaitGroup{}
|
||||
wg.Add(1)
|
||||
|
||||
cron := newWithSeconds()
|
||||
cron.AddFunc("* * * * * ?", func() { wg.Done() })
|
||||
cron.Start()
|
||||
defer cron.Stop()
|
||||
|
||||
// Give cron 2 seconds to run our job (which is always activated).
|
||||
select {
|
||||
case <-time.After(OneSecond):
|
||||
t.Fatal("expected job runs")
|
||||
case <-wait(wg):
|
||||
}
|
||||
}
|
||||
|
||||
// Start cron, add a job, expect it runs.
|
||||
func TestAddWhileRunning(t *testing.T) {
|
||||
wg := &sync.WaitGroup{}
|
||||
wg.Add(1)
|
||||
|
||||
cron := newWithSeconds()
|
||||
cron.Start()
|
||||
defer cron.Stop()
|
||||
cron.AddFunc("* * * * * ?", func() { wg.Done() })
|
||||
|
||||
select {
|
||||
case <-time.After(OneSecond):
|
||||
t.Fatal("expected job runs")
|
||||
case <-wait(wg):
|
||||
}
|
||||
}
|
||||
|
||||
// Test for #34. Adding a job after calling start results in multiple job invocations
|
||||
func TestAddWhileRunningWithDelay(t *testing.T) {
|
||||
cron := newWithSeconds()
|
||||
cron.Start()
|
||||
defer cron.Stop()
|
||||
time.Sleep(5 * time.Second)
|
||||
var calls int64
|
||||
cron.AddFunc("* * * * * *", func() { atomic.AddInt64(&calls, 1) })
|
||||
|
||||
<-time.After(OneSecond)
|
||||
if atomic.LoadInt64(&calls) != 1 {
|
||||
t.Errorf("called %d times, expected 1\n", calls)
|
||||
}
|
||||
}
|
||||
|
||||
// Add a job, remove a job, start cron, expect nothing runs.
|
||||
func TestRemoveBeforeRunning(t *testing.T) {
|
||||
wg := &sync.WaitGroup{}
|
||||
wg.Add(1)
|
||||
|
||||
cron := newWithSeconds()
|
||||
id, _ := cron.AddFunc("* * * * * ?", func() { wg.Done() })
|
||||
cron.Remove(id)
|
||||
cron.Start()
|
||||
defer cron.Stop()
|
||||
|
||||
select {
|
||||
case <-time.After(OneSecond):
|
||||
// Success, shouldn't run
|
||||
case <-wait(wg):
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
|
||||
// Start cron, add a job, remove it, expect it doesn't run.
|
||||
func TestRemoveWhileRunning(t *testing.T) {
|
||||
wg := &sync.WaitGroup{}
|
||||
wg.Add(1)
|
||||
|
||||
cron := newWithSeconds()
|
||||
cron.Start()
|
||||
defer cron.Stop()
|
||||
id, _ := cron.AddFunc("* * * * * ?", func() { wg.Done() })
|
||||
cron.Remove(id)
|
||||
|
||||
select {
|
||||
case <-time.After(OneSecond):
|
||||
case <-wait(wg):
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
|
||||
// Test timing with Entries.
|
||||
func TestSnapshotEntries(t *testing.T) {
|
||||
wg := &sync.WaitGroup{}
|
||||
wg.Add(1)
|
||||
|
||||
cron := New()
|
||||
cron.AddFunc("@every 2s", func() { wg.Done() })
|
||||
cron.Start()
|
||||
defer cron.Stop()
|
||||
|
||||
// Cron should fire in 2 seconds. After 1 second, call Entries.
|
||||
select {
|
||||
case <-time.After(OneSecond):
|
||||
cron.Entries()
|
||||
}
|
||||
|
||||
// Even though Entries was called, the cron should fire at the 2 second mark.
|
||||
select {
|
||||
case <-time.After(OneSecond):
|
||||
t.Error("expected job runs at 2 second mark")
|
||||
case <-wait(wg):
|
||||
}
|
||||
}
|
||||
|
||||
// Test that the entries are correctly sorted.
|
||||
// Add a bunch of long-in-the-future entries, and an immediate entry, and ensure
|
||||
// that the immediate entry runs immediately.
|
||||
// Also: Test that multiple jobs run in the same instant.
|
||||
func TestMultipleEntries(t *testing.T) {
|
||||
wg := &sync.WaitGroup{}
|
||||
wg.Add(2)
|
||||
|
||||
cron := newWithSeconds()
|
||||
cron.AddFunc("0 0 0 1 1 ?", func() {})
|
||||
cron.AddFunc("* * * * * ?", func() { wg.Done() })
|
||||
id1, _ := cron.AddFunc("* * * * * ?", func() { t.Fatal() })
|
||||
id2, _ := cron.AddFunc("* * * * * ?", func() { t.Fatal() })
|
||||
cron.AddFunc("0 0 0 31 12 ?", func() {})
|
||||
cron.AddFunc("* * * * * ?", func() { wg.Done() })
|
||||
|
||||
cron.Remove(id1)
|
||||
cron.Start()
|
||||
cron.Remove(id2)
|
||||
defer cron.Stop()
|
||||
|
||||
select {
|
||||
case <-time.After(OneSecond):
|
||||
t.Error("expected job run in proper order")
|
||||
case <-wait(wg):
|
||||
}
|
||||
}
|
||||
|
||||
// Test running the same job twice.
|
||||
func TestRunningJobTwice(t *testing.T) {
|
||||
wg := &sync.WaitGroup{}
|
||||
wg.Add(2)
|
||||
|
||||
cron := newWithSeconds()
|
||||
cron.AddFunc("0 0 0 1 1 ?", func() {})
|
||||
cron.AddFunc("0 0 0 31 12 ?", func() {})
|
||||
cron.AddFunc("* * * * * ?", func() { wg.Done() })
|
||||
|
||||
cron.Start()
|
||||
defer cron.Stop()
|
||||
|
||||
select {
|
||||
case <-time.After(2 * OneSecond):
|
||||
t.Error("expected job fires 2 times")
|
||||
case <-wait(wg):
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunningMultipleSchedules(t *testing.T) {
|
||||
wg := &sync.WaitGroup{}
|
||||
wg.Add(2)
|
||||
|
||||
cron := newWithSeconds()
|
||||
cron.AddFunc("0 0 0 1 1 ?", func() {})
|
||||
cron.AddFunc("0 0 0 31 12 ?", func() {})
|
||||
cron.AddFunc("* * * * * ?", func() { wg.Done() })
|
||||
cron.Schedule(Every(time.Minute), FuncJob(func() {}))
|
||||
cron.Schedule(Every(time.Second), FuncJob(func() { wg.Done() }))
|
||||
cron.Schedule(Every(time.Hour), FuncJob(func() {}))
|
||||
|
||||
cron.Start()
|
||||
defer cron.Stop()
|
||||
|
||||
select {
|
||||
case <-time.After(2 * OneSecond):
|
||||
t.Error("expected job fires 2 times")
|
||||
case <-wait(wg):
|
||||
}
|
||||
}
|
||||
|
||||
// Test that the cron is run in the local time zone (as opposed to UTC).
|
||||
func TestLocalTimezone(t *testing.T) {
|
||||
wg := &sync.WaitGroup{}
|
||||
wg.Add(2)
|
||||
|
||||
now := time.Now()
|
||||
// FIX: Issue #205
|
||||
// This calculation doesn't work in seconds 58 or 59.
|
||||
// Take the easy way out and sleep.
|
||||
if now.Second() >= 58 {
|
||||
time.Sleep(2 * time.Second)
|
||||
now = time.Now()
|
||||
}
|
||||
spec := fmt.Sprintf("%d,%d %d %d %d %d ?",
|
||||
now.Second()+1, now.Second()+2, now.Minute(), now.Hour(), now.Day(), now.Month())
|
||||
|
||||
cron := newWithSeconds()
|
||||
cron.AddFunc(spec, func() { wg.Done() })
|
||||
cron.Start()
|
||||
defer cron.Stop()
|
||||
|
||||
select {
|
||||
case <-time.After(OneSecond * 2):
|
||||
t.Error("expected job fires 2 times")
|
||||
case <-wait(wg):
|
||||
}
|
||||
}
|
||||
|
||||
// Test that the cron is run in the given time zone (as opposed to local).
|
||||
func TestNonLocalTimezone(t *testing.T) {
|
||||
wg := &sync.WaitGroup{}
|
||||
wg.Add(2)
|
||||
|
||||
loc, err := time.LoadLocation("Atlantic/Cape_Verde")
|
||||
if err != nil {
|
||||
fmt.Printf("Failed to load time zone Atlantic/Cape_Verde: %+v", err)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
now := time.Now().In(loc)
|
||||
// FIX: Issue #205
|
||||
// This calculation doesn't work in seconds 58 or 59.
|
||||
// Take the easy way out and sleep.
|
||||
if now.Second() >= 58 {
|
||||
time.Sleep(2 * time.Second)
|
||||
now = time.Now().In(loc)
|
||||
}
|
||||
spec := fmt.Sprintf("%d,%d %d %d %d %d ?",
|
||||
now.Second()+1, now.Second()+2, now.Minute(), now.Hour(), now.Day(), now.Month())
|
||||
|
||||
cron := New(WithLocation(loc), WithParser(secondParser))
|
||||
cron.AddFunc(spec, func() { wg.Done() })
|
||||
cron.Start()
|
||||
defer cron.Stop()
|
||||
|
||||
select {
|
||||
case <-time.After(OneSecond * 2):
|
||||
t.Error("expected job fires 2 times")
|
||||
case <-wait(wg):
|
||||
}
|
||||
}
|
||||
|
||||
// Test that calling stop before start silently returns without
|
||||
// blocking the stop channel.
|
||||
func TestStopWithoutStart(t *testing.T) {
|
||||
cron := New()
|
||||
cron.Stop()
|
||||
}
|
||||
|
||||
type testJob struct {
|
||||
wg *sync.WaitGroup
|
||||
name string
|
||||
}
|
||||
|
||||
func (t testJob) Run() {
|
||||
t.wg.Done()
|
||||
}
|
||||
|
||||
// Test that adding an invalid job spec returns an error
|
||||
func TestInvalidJobSpec(t *testing.T) {
|
||||
cron := New()
|
||||
_, err := cron.AddJob("this will not parse", nil)
|
||||
if err == nil {
|
||||
t.Errorf("expected an error with invalid spec, got nil")
|
||||
}
|
||||
}
|
||||
|
||||
// Test blocking run method behaves as Start()
|
||||
func TestBlockingRun(t *testing.T) {
|
||||
wg := &sync.WaitGroup{}
|
||||
wg.Add(1)
|
||||
|
||||
cron := newWithSeconds()
|
||||
cron.AddFunc("* * * * * ?", func() { wg.Done() })
|
||||
|
||||
var unblockChan = make(chan struct{})
|
||||
|
||||
go func() {
|
||||
cron.Run()
|
||||
close(unblockChan)
|
||||
}()
|
||||
defer cron.Stop()
|
||||
|
||||
select {
|
||||
case <-time.After(OneSecond):
|
||||
t.Error("expected job fires")
|
||||
case <-unblockChan:
|
||||
t.Error("expected that Run() blocks")
|
||||
case <-wait(wg):
|
||||
}
|
||||
}
|
||||
|
||||
// Test that double-running is a no-op
|
||||
func TestStartNoop(t *testing.T) {
|
||||
var tickChan = make(chan struct{}, 2)
|
||||
|
||||
cron := newWithSeconds()
|
||||
cron.AddFunc("* * * * * ?", func() {
|
||||
tickChan <- struct{}{}
|
||||
})
|
||||
|
||||
cron.Start()
|
||||
defer cron.Stop()
|
||||
|
||||
// Wait for the first firing to ensure the runner is going
|
||||
<-tickChan
|
||||
|
||||
cron.Start()
|
||||
|
||||
<-tickChan
|
||||
|
||||
// Fail if this job fires again in a short period, indicating a double-run
|
||||
select {
|
||||
case <-time.After(time.Millisecond):
|
||||
case <-tickChan:
|
||||
t.Error("expected job fires exactly twice")
|
||||
}
|
||||
}
|
||||
|
||||
// Simple test using Runnables.
|
||||
func TestJob(t *testing.T) {
|
||||
wg := &sync.WaitGroup{}
|
||||
wg.Add(1)
|
||||
|
||||
cron := newWithSeconds()
|
||||
cron.AddJob("0 0 0 30 Feb ?", testJob{wg, "job0"})
|
||||
cron.AddJob("0 0 0 1 1 ?", testJob{wg, "job1"})
|
||||
job2, _ := cron.AddJob("* * * * * ?", testJob{wg, "job2"})
|
||||
cron.AddJob("1 0 0 1 1 ?", testJob{wg, "job3"})
|
||||
cron.Schedule(Every(5*time.Second+5*time.Nanosecond), testJob{wg, "job4"})
|
||||
job5 := cron.Schedule(Every(5*time.Minute), testJob{wg, "job5"})
|
||||
|
||||
// Test getting an Entry pre-Start.
|
||||
if actualName := cron.Entry(job2).Job.(testJob).name; actualName != "job2" {
|
||||
t.Error("wrong job retrieved:", actualName)
|
||||
}
|
||||
if actualName := cron.Entry(job5).Job.(testJob).name; actualName != "job5" {
|
||||
t.Error("wrong job retrieved:", actualName)
|
||||
}
|
||||
|
||||
cron.Start()
|
||||
defer cron.Stop()
|
||||
|
||||
select {
|
||||
case <-time.After(OneSecond):
|
||||
t.FailNow()
|
||||
case <-wait(wg):
|
||||
}
|
||||
|
||||
// Ensure the entries are in the right order.
|
||||
expecteds := []string{"job2", "job4", "job5", "job1", "job3", "job0"}
|
||||
|
||||
var actuals []string
|
||||
for _, entry := range cron.Entries() {
|
||||
actuals = append(actuals, entry.Job.(testJob).name)
|
||||
}
|
||||
|
||||
for i, expected := range expecteds {
|
||||
if actuals[i] != expected {
|
||||
t.Fatalf("Jobs not in the right order. (expected) %s != %s (actual)", expecteds, actuals)
|
||||
}
|
||||
}
|
||||
|
||||
// Test getting Entries.
|
||||
if actualName := cron.Entry(job2).Job.(testJob).name; actualName != "job2" {
|
||||
t.Error("wrong job retrieved:", actualName)
|
||||
}
|
||||
if actualName := cron.Entry(job5).Job.(testJob).name; actualName != "job5" {
|
||||
t.Error("wrong job retrieved:", actualName)
|
||||
}
|
||||
}
|
||||
|
||||
// Issue #206
|
||||
// Ensure that the next run of a job after removing an entry is accurate.
|
||||
func TestScheduleAfterRemoval(t *testing.T) {
|
||||
var wg1 sync.WaitGroup
|
||||
var wg2 sync.WaitGroup
|
||||
wg1.Add(1)
|
||||
wg2.Add(1)
|
||||
|
||||
// The first time this job is run, set a timer and remove the other job
|
||||
// 750ms later. Correct behavior would be to still run the job again in
|
||||
// 250ms, but the bug would cause it to run instead 1s later.
|
||||
|
||||
var calls int
|
||||
var mu sync.Mutex
|
||||
|
||||
cron := newWithSeconds()
|
||||
hourJob := cron.Schedule(Every(time.Hour), FuncJob(func() {}))
|
||||
cron.Schedule(Every(time.Second), FuncJob(func() {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
switch calls {
|
||||
case 0:
|
||||
wg1.Done()
|
||||
calls++
|
||||
case 1:
|
||||
time.Sleep(750 * time.Millisecond)
|
||||
cron.Remove(hourJob)
|
||||
calls++
|
||||
case 2:
|
||||
calls++
|
||||
wg2.Done()
|
||||
case 3:
|
||||
panic("unexpected 3rd call")
|
||||
}
|
||||
}))
|
||||
|
||||
cron.Start()
|
||||
defer cron.Stop()
|
||||
|
||||
// the first run might be any length of time 0 - 1s, since the schedule
|
||||
// rounds to the second. wait for the first run to true up.
|
||||
wg1.Wait()
|
||||
|
||||
select {
|
||||
case <-time.After(2 * OneSecond):
|
||||
t.Error("expected job fires 2 times")
|
||||
case <-wait(&wg2):
|
||||
}
|
||||
}
|
||||
|
||||
type ZeroSchedule struct{}
|
||||
|
||||
func (*ZeroSchedule) Next(time.Time) time.Time {
|
||||
return time.Time{}
|
||||
}
|
||||
|
||||
// Tests that job without time does not run
|
||||
func TestJobWithZeroTimeDoesNotRun(t *testing.T) {
|
||||
cron := newWithSeconds()
|
||||
var calls int64
|
||||
cron.AddFunc("* * * * * *", func() { atomic.AddInt64(&calls, 1) })
|
||||
cron.Schedule(new(ZeroSchedule), FuncJob(func() { t.Error("expected zero task will not run") }))
|
||||
cron.Start()
|
||||
defer cron.Stop()
|
||||
<-time.After(OneSecond)
|
||||
if atomic.LoadInt64(&calls) != 1 {
|
||||
t.Errorf("called %d times, expected 1\n", calls)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStopAndWait(t *testing.T) {
|
||||
t.Run("nothing running, returns immediately", func(t *testing.T) {
|
||||
cron := newWithSeconds()
|
||||
cron.Start()
|
||||
ctx := cron.Stop()
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
case <-time.After(time.Millisecond):
|
||||
t.Error("context was not done immediately")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("repeated calls to Stop", func(t *testing.T) {
|
||||
cron := newWithSeconds()
|
||||
cron.Start()
|
||||
_ = cron.Stop()
|
||||
time.Sleep(time.Millisecond)
|
||||
ctx := cron.Stop()
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
case <-time.After(time.Millisecond):
|
||||
t.Error("context was not done immediately")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("a couple fast jobs added, still returns immediately", func(t *testing.T) {
|
||||
cron := newWithSeconds()
|
||||
cron.AddFunc("* * * * * *", func() {})
|
||||
cron.Start()
|
||||
cron.AddFunc("* * * * * *", func() {})
|
||||
cron.AddFunc("* * * * * *", func() {})
|
||||
cron.AddFunc("* * * * * *", func() {})
|
||||
time.Sleep(time.Second)
|
||||
ctx := cron.Stop()
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
case <-time.After(time.Millisecond):
|
||||
t.Error("context was not done immediately")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("a couple fast jobs and a slow job added, waits for slow job", func(t *testing.T) {
|
||||
cron := newWithSeconds()
|
||||
cron.AddFunc("* * * * * *", func() {})
|
||||
cron.Start()
|
||||
cron.AddFunc("* * * * * *", func() { time.Sleep(2 * time.Second) })
|
||||
cron.AddFunc("* * * * * *", func() {})
|
||||
time.Sleep(time.Second)
|
||||
|
||||
ctx := cron.Stop()
|
||||
|
||||
// Verify that it is not done for at least 750ms
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
t.Error("context was done too quickly immediately")
|
||||
case <-time.After(750 * time.Millisecond):
|
||||
// expected, because the job sleeping for 1 second is still running
|
||||
}
|
||||
|
||||
// Verify that it IS done in the next 500ms (giving 250ms buffer)
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
// expected
|
||||
case <-time.After(1500 * time.Millisecond):
|
||||
t.Error("context not done after job should have completed")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("repeated calls to stop, waiting for completion and after", func(t *testing.T) {
|
||||
cron := newWithSeconds()
|
||||
cron.AddFunc("* * * * * *", func() {})
|
||||
cron.AddFunc("* * * * * *", func() { time.Sleep(2 * time.Second) })
|
||||
cron.Start()
|
||||
cron.AddFunc("* * * * * *", func() {})
|
||||
time.Sleep(time.Second)
|
||||
ctx := cron.Stop()
|
||||
ctx2 := cron.Stop()
|
||||
|
||||
// Verify that it is not done for at least 1500ms
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
t.Error("context was done too quickly immediately")
|
||||
case <-ctx2.Done():
|
||||
t.Error("context2 was done too quickly immediately")
|
||||
case <-time.After(1500 * time.Millisecond):
|
||||
// expected, because the job sleeping for 2 seconds is still running
|
||||
}
|
||||
|
||||
// Verify that it IS done in the next 1s (giving 500ms buffer)
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
// expected
|
||||
case <-time.After(time.Second):
|
||||
t.Error("context not done after job should have completed")
|
||||
}
|
||||
|
||||
// Verify that ctx2 is also done.
|
||||
select {
|
||||
case <-ctx2.Done():
|
||||
// expected
|
||||
case <-time.After(time.Millisecond):
|
||||
t.Error("context2 not done even though context1 is")
|
||||
}
|
||||
|
||||
// Verify that a new context retrieved from stop is immediately done.
|
||||
ctx3 := cron.Stop()
|
||||
select {
|
||||
case <-ctx3.Done():
|
||||
// expected
|
||||
case <-time.After(time.Millisecond):
|
||||
t.Error("context not done even when cron Stop is completed")
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func TestMultiThreadedStartAndStop(t *testing.T) {
|
||||
cron := New()
|
||||
go cron.Run()
|
||||
time.Sleep(2 * time.Millisecond)
|
||||
cron.Stop()
|
||||
}
|
||||
|
||||
func wait(wg *sync.WaitGroup) chan bool {
|
||||
ch := make(chan bool)
|
||||
go func() {
|
||||
wg.Wait()
|
||||
ch <- true
|
||||
}()
|
||||
return ch
|
||||
}
|
||||
|
||||
func stop(cron *Cron) chan bool {
|
||||
ch := make(chan bool)
|
||||
go func() {
|
||||
cron.Stop()
|
||||
ch <- true
|
||||
}()
|
||||
return ch
|
||||
}
|
||||
|
||||
// newWithSeconds returns a Cron with the seconds field enabled.
|
||||
func newWithSeconds() *Cron {
|
||||
return New(WithParser(secondParser), WithChain())
|
||||
}
|
||||
@ -1,212 +0,0 @@
|
||||
/*
|
||||
Package cron implements a cron spec parser and job runner.
|
||||
|
||||
Usage
|
||||
|
||||
Callers may register Funcs to be invoked on a given schedule. Cron will run
|
||||
them in their own goroutines.
|
||||
|
||||
c := cron.New()
|
||||
c.AddFunc("30 * * * *", func() { fmt.Println("Every hour on the half hour") })
|
||||
c.AddFunc("30 3-6,20-23 * * *", func() { fmt.Println(".. in the range 3-6am, 8-11pm") })
|
||||
c.AddFunc("CRON_TZ=Asia/Tokyo 30 04 * * * *", func() { fmt.Println("Runs at 04:30 Tokyo time every day") })
|
||||
c.AddFunc("@hourly", func() { fmt.Println("Every hour, starting an hour from now") })
|
||||
c.AddFunc("@every 1h30m", func() { fmt.Println("Every hour thirty, starting an hour thirty from now") })
|
||||
c.Start()
|
||||
..
|
||||
// Funcs are invoked in their own goroutine, asynchronously.
|
||||
...
|
||||
// Funcs may also be added to a running Cron
|
||||
c.AddFunc("@daily", func() { fmt.Println("Every day") })
|
||||
..
|
||||
// Inspect the cron job entries' next and previous run times.
|
||||
inspect(c.Entries())
|
||||
..
|
||||
c.Stop() // Stop the scheduler (does not stop any jobs already running).
|
||||
|
||||
CRON Expression Format
|
||||
|
||||
A cron expression represents a set of times, using 5 space-separated fields.
|
||||
|
||||
Field name | Mandatory? | Allowed values | Allowed special characters
|
||||
---------- | ---------- | -------------- | --------------------------
|
||||
Minutes | Yes | 0-59 | * / , -
|
||||
Hours | Yes | 0-23 | * / , -
|
||||
Day of month | Yes | 1-31 | * / , - ?
|
||||
Month | Yes | 1-12 or JAN-DEC | * / , -
|
||||
Day of week | Yes | 0-6 or SUN-SAT | * / , - ?
|
||||
|
||||
Month and Day-of-week field values are case insensitive. "SUN", "Sun", and
|
||||
"sun" are equally accepted.
|
||||
|
||||
The specific interpretation of the format is based on the Cron Wikipedia page:
|
||||
https://en.wikipedia.org/wiki/Cron
|
||||
|
||||
Alternative Formats
|
||||
|
||||
Alternative Cron expression formats support other fields like seconds. You can
|
||||
implement that by creating a custom Parser as follows.
|
||||
|
||||
cron.New(
|
||||
cron.WithParser(
|
||||
cron.SecondOptional | cron.Hour | cron.Dom | cron.Month | cron.Dow | cron.Descriptor))
|
||||
|
||||
The most popular alternative Cron expression format is Quartz:
|
||||
http://www.quartz-scheduler.org/documentation/quartz-2.x/tutorials/crontrigger.html
|
||||
|
||||
Special Characters
|
||||
|
||||
Asterisk ( * )
|
||||
|
||||
The asterisk indicates that the cron expression will match for all values of the
|
||||
field; e.g., using an asterisk in the 5th field (month) would indicate every
|
||||
month.
|
||||
|
||||
Slash ( / )
|
||||
|
||||
Slashes are used to describe increments of ranges. For example 3-59/15 in the
|
||||
1st field (minutes) would indicate the 3rd minute of the hour and every 15
|
||||
minutes thereafter. The form "*\/..." is equivalent to the form "first-last/...",
|
||||
that is, an increment over the largest possible range of the field. The form
|
||||
"N/..." is accepted as meaning "N-MAX/...", that is, starting at N, use the
|
||||
increment until the end of that specific range. It does not wrap around.
|
||||
|
||||
Comma ( , )
|
||||
|
||||
Commas are used to separate items of a list. For example, using "MON,WED,FRI" in
|
||||
the 5th field (day of week) would mean Mondays, Wednesdays and Fridays.
|
||||
|
||||
Hyphen ( - )
|
||||
|
||||
Hyphens are used to define ranges. For example, 9-17 would indicate every
|
||||
hour between 9am and 5pm inclusive.
|
||||
|
||||
Question mark ( ? )
|
||||
|
||||
Question mark may be used instead of '*' for leaving either day-of-month or
|
||||
day-of-week blank.
|
||||
|
||||
Predefined schedules
|
||||
|
||||
You may use one of several pre-defined schedules in place of a cron expression.
|
||||
|
||||
Entry | Description | Equivalent To
|
||||
----- | ----------- | -------------
|
||||
@yearly (or @annually) | Run once a year, midnight, Jan. 1st | 0 0 1 1 *
|
||||
@monthly | Run once a month, midnight, first of month | 0 0 1 * *
|
||||
@weekly | Run once a week, midnight between Sat/Sun | 0 0 * * 0
|
||||
@daily (or @midnight) | Run once a day, midnight | 0 0 * * *
|
||||
@hourly | Run once an hour, beginning of hour | 0 * * * *
|
||||
|
||||
Intervals
|
||||
|
||||
You may also schedule a job to execute at fixed intervals, starting at the time it's added
|
||||
or cron is run. This is supported by formatting the cron spec like this:
|
||||
|
||||
@every <duration>
|
||||
|
||||
where "duration" is a string accepted by time.ParseDuration
|
||||
(http://golang.org/pkg/time/#ParseDuration).
|
||||
|
||||
For example, "@every 1h30m10s" would indicate a schedule that activates after
|
||||
1 hour, 30 minutes, 10 seconds, and then every interval after that.
|
||||
|
||||
Note: The interval does not take the job runtime into account. For example,
|
||||
if a job takes 3 minutes to run, and it is scheduled to run every 5 minutes,
|
||||
it will have only 2 minutes of idle time between each run.
|
||||
|
||||
Time zones
|
||||
|
||||
By default, all interpretation and scheduling is done in the machine's local
|
||||
time zone (time.Local). You can specify a different time zone on construction:
|
||||
|
||||
cron.New(
|
||||
cron.WithLocation(time.UTC))
|
||||
|
||||
Individual cron schedules may also override the time zone they are to be
|
||||
interpreted in by providing an additional space-separated field at the beginning
|
||||
of the cron spec, of the form "CRON_TZ=Asia/Tokyo".
|
||||
|
||||
For example:
|
||||
|
||||
# Runs at 6am in time.Local
|
||||
cron.New().AddFunc("0 6 * * ?", ...)
|
||||
|
||||
# Runs at 6am in America/New_York
|
||||
nyc, _ := time.LoadLocation("America/New_York")
|
||||
c := cron.New(cron.WithLocation(nyc))
|
||||
c.AddFunc("0 6 * * ?", ...)
|
||||
|
||||
# Runs at 6am in Asia/Tokyo
|
||||
cron.New().AddFunc("CRON_TZ=Asia/Tokyo 0 6 * * ?", ...)
|
||||
|
||||
# Runs at 6am in Asia/Tokyo
|
||||
c := cron.New(cron.WithLocation(nyc))
|
||||
c.SetLocation("America/New_York")
|
||||
c.AddFunc("CRON_TZ=Asia/Tokyo 0 6 * * ?", ...)
|
||||
|
||||
The prefix "TZ=(TIME ZONE)" is also supported for legacy compatibility.
|
||||
|
||||
Be aware that jobs scheduled during daylight-savings leap-ahead transitions will
|
||||
not be run!
|
||||
|
||||
Job Wrappers / Chain
|
||||
|
||||
A Cron runner may be configured with a chain of job wrappers to add
|
||||
cross-cutting functionality to all submitted jobs. For example, they may be used
|
||||
to achieve the following effects:
|
||||
|
||||
- Recover any panics from jobs (activated by default)
|
||||
- Delay a job's execution if the previous run hasn't completed yet
|
||||
- Skip a job's execution if the previous run hasn't completed yet
|
||||
- Log each job's invocations
|
||||
|
||||
Install wrappers for all jobs added to a cron using the `cron.WithChain` option:
|
||||
|
||||
cron.New(cron.WithChain(
|
||||
cron.SkipIfStillRunning(logger),
|
||||
))
|
||||
|
||||
Install wrappers for individual jobs by explicitly wrapping them:
|
||||
|
||||
job = cron.NewChain(
|
||||
cron.SkipIfStillRunning(logger),
|
||||
).Then(job)
|
||||
|
||||
Thread safety
|
||||
|
||||
Since the Cron service runs concurrently with the calling code, some amount of
|
||||
care must be taken to ensure proper synchronization.
|
||||
|
||||
All cron methods are designed to be correctly synchronized as long as the caller
|
||||
ensures that invocations have a clear happens-before ordering between them.
|
||||
|
||||
Logging
|
||||
|
||||
Cron defines a Logger interface that is a subset of the one defined in
|
||||
github.com/go-logr/logr. It has two logging levels (Info and Error), and
|
||||
parameters are key/value pairs. This makes it possible for cron logging to plug
|
||||
into structured logging systems. An adapter, [Verbose]PrintfLogger, is provided
|
||||
to wrap the standard library *log.Logger.
|
||||
|
||||
For additional insight into Cron operations, verbose logging may be activated
|
||||
which will record job runs, scheduling decisions, and added or removed jobs.
|
||||
Activate it with a one-off logger as follows:
|
||||
|
||||
cron.New(
|
||||
cron.WithLogger(
|
||||
cron.VerbosePrintfLogger(log.New(os.Stdout, "cron: ", log.LstdFlags))))
|
||||
|
||||
|
||||
Implementation
|
||||
|
||||
Cron entries are stored in an array, sorted by their next activation time. Cron
|
||||
sleeps until the next job is due to be run.
|
||||
|
||||
Upon waking:
|
||||
- it runs each entry that is active on that second
|
||||
- it calculates the next run times for the jobs that were run
|
||||
- it re-sorts the array of entries by next activation time.
|
||||
- it goes to sleep until the soonest job.
|
||||
*/
|
||||
package cron
|
||||
@ -1,86 +0,0 @@
|
||||
package cron
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// DefaultLogger is used by Cron if none is specified.
|
||||
var DefaultLogger Logger = PrintfLogger(log.New(os.Stdout, "cron: ", log.LstdFlags))
|
||||
|
||||
// DiscardLogger can be used by callers to discard all log messages.
|
||||
var DiscardLogger Logger = PrintfLogger(log.New(ioutil.Discard, "", 0))
|
||||
|
||||
// Logger is the interface used in this package for logging, so that any backend
|
||||
// can be plugged in. It is a subset of the github.com/go-logr/logr interface.
|
||||
type Logger interface {
|
||||
// Info logs routine messages about cron's operation.
|
||||
Info(msg string, keysAndValues ...interface{})
|
||||
// Error logs an error condition.
|
||||
Error(err error, msg string, keysAndValues ...interface{})
|
||||
}
|
||||
|
||||
// PrintfLogger wraps a Printf-based logger (such as the standard library "log")
|
||||
// into an implementation of the Logger interface which logs errors only.
|
||||
func PrintfLogger(l interface{ Printf(string, ...interface{}) }) Logger {
|
||||
return printfLogger{l, false}
|
||||
}
|
||||
|
||||
// VerbosePrintfLogger wraps a Printf-based logger (such as the standard library
|
||||
// "log") into an implementation of the Logger interface which logs everything.
|
||||
func VerbosePrintfLogger(l interface{ Printf(string, ...interface{}) }) Logger {
|
||||
return printfLogger{l, true}
|
||||
}
|
||||
|
||||
type printfLogger struct {
|
||||
logger interface{ Printf(string, ...interface{}) }
|
||||
logInfo bool
|
||||
}
|
||||
|
||||
func (pl printfLogger) Info(msg string, keysAndValues ...interface{}) {
|
||||
if pl.logInfo {
|
||||
keysAndValues = formatTimes(keysAndValues)
|
||||
pl.logger.Printf(
|
||||
formatString(len(keysAndValues)),
|
||||
append([]interface{}{msg}, keysAndValues...)...)
|
||||
}
|
||||
}
|
||||
|
||||
func (pl printfLogger) Error(err error, msg string, keysAndValues ...interface{}) {
|
||||
keysAndValues = formatTimes(keysAndValues)
|
||||
pl.logger.Printf(
|
||||
formatString(len(keysAndValues)+2),
|
||||
append([]interface{}{msg, "error", err}, keysAndValues...)...)
|
||||
}
|
||||
|
||||
// formatString returns a logfmt-like format string for the number of
|
||||
// key/values.
|
||||
func formatString(numKeysAndValues int) string {
|
||||
var sb strings.Builder
|
||||
sb.WriteString("%s")
|
||||
if numKeysAndValues > 0 {
|
||||
sb.WriteString(", ")
|
||||
}
|
||||
for i := 0; i < numKeysAndValues/2; i++ {
|
||||
if i > 0 {
|
||||
sb.WriteString(", ")
|
||||
}
|
||||
sb.WriteString("%v=%v")
|
||||
}
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
// formatTimes formats any time.Time values as RFC3339.
|
||||
func formatTimes(keysAndValues []interface{}) []interface{} {
|
||||
var formattedArgs []interface{}
|
||||
for _, arg := range keysAndValues {
|
||||
if t, ok := arg.(time.Time); ok {
|
||||
arg = t.Format(time.RFC3339)
|
||||
}
|
||||
formattedArgs = append(formattedArgs, arg)
|
||||
}
|
||||
return formattedArgs
|
||||
}
|
||||
@ -1,45 +0,0 @@
|
||||
package cron
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// Option represents a modification to the default behavior of a Cron.
|
||||
type Option func(*Cron)
|
||||
|
||||
// WithLocation overrides the timezone of the cron instance.
|
||||
func WithLocation(loc *time.Location) Option {
|
||||
return func(c *Cron) {
|
||||
c.location = loc
|
||||
}
|
||||
}
|
||||
|
||||
// WithSeconds overrides the parser used for interpreting job schedules to
|
||||
// include a seconds field as the first one.
|
||||
func WithSeconds() Option {
|
||||
return WithParser(NewParser(
|
||||
Second | Minute | Hour | Dom | Month | Dow | Descriptor,
|
||||
))
|
||||
}
|
||||
|
||||
// WithParser overrides the parser used for interpreting job schedules.
|
||||
func WithParser(p Parser) Option {
|
||||
return func(c *Cron) {
|
||||
c.parser = p
|
||||
}
|
||||
}
|
||||
|
||||
// WithChain specifies Job wrappers to apply to all jobs added to this cron.
|
||||
// Refer to the Chain* functions in this package for provided wrappers.
|
||||
func WithChain(wrappers ...JobWrapper) Option {
|
||||
return func(c *Cron) {
|
||||
c.chain = NewChain(wrappers...)
|
||||
}
|
||||
}
|
||||
|
||||
// WithLogger uses the provided logger.
|
||||
func WithLogger(logger Logger) Option {
|
||||
return func(c *Cron) {
|
||||
c.logger = logger
|
||||
}
|
||||
}
|
||||
@ -1,42 +0,0 @@
|
||||
package cron
|
||||
|
||||
import (
|
||||
"log"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestWithLocation(t *testing.T) {
|
||||
c := New(WithLocation(time.UTC))
|
||||
if c.location != time.UTC {
|
||||
t.Errorf("expected UTC, got %v", c.location)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithParser(t *testing.T) {
|
||||
var parser = NewParser(Dow)
|
||||
c := New(WithParser(parser))
|
||||
if c.parser != parser {
|
||||
t.Error("expected provided parser")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithVerboseLogger(t *testing.T) {
|
||||
var buf syncWriter
|
||||
var logger = log.New(&buf, "", log.LstdFlags)
|
||||
c := New(WithLogger(VerbosePrintfLogger(logger)))
|
||||
if c.logger.(printfLogger).logger != logger {
|
||||
t.Error("expected provided logger")
|
||||
}
|
||||
|
||||
c.AddFunc("@every 1s", func() {})
|
||||
c.Start()
|
||||
time.Sleep(OneSecond)
|
||||
c.Stop()
|
||||
out := buf.String()
|
||||
if !strings.Contains(out, "schedule,") ||
|
||||
!strings.Contains(out, "run,") {
|
||||
t.Error("expected to see some actions, got:", out)
|
||||
}
|
||||
}
|
||||
@ -1,434 +0,0 @@
|
||||
package cron
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Configuration options for creating a parser. Most options specify which
|
||||
// fields should be included, while others enable features. If a field is not
|
||||
// included the parser will assume a default value. These options do not change
|
||||
// the order fields are parse in.
|
||||
type ParseOption int
|
||||
|
||||
const (
|
||||
Second ParseOption = 1 << iota // Seconds field, default 0
|
||||
SecondOptional // Optional seconds field, default 0
|
||||
Minute // Minutes field, default 0
|
||||
Hour // Hours field, default 0
|
||||
Dom // Day of month field, default *
|
||||
Month // Month field, default *
|
||||
Dow // Day of week field, default *
|
||||
DowOptional // Optional day of week field, default *
|
||||
Descriptor // Allow descriptors such as @monthly, @weekly, etc.
|
||||
)
|
||||
|
||||
var places = []ParseOption{
|
||||
Second,
|
||||
Minute,
|
||||
Hour,
|
||||
Dom,
|
||||
Month,
|
||||
Dow,
|
||||
}
|
||||
|
||||
var defaults = []string{
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"*",
|
||||
"*",
|
||||
"*",
|
||||
}
|
||||
|
||||
// A custom Parser that can be configured.
|
||||
type Parser struct {
|
||||
options ParseOption
|
||||
}
|
||||
|
||||
// NewParser creates a Parser with custom options.
|
||||
//
|
||||
// It panics if more than one Optional is given, since it would be impossible to
|
||||
// correctly infer which optional is provided or missing in general.
|
||||
//
|
||||
// Examples
|
||||
//
|
||||
// // Standard parser without descriptors
|
||||
// specParser := NewParser(Minute | Hour | Dom | Month | Dow)
|
||||
// sched, err := specParser.Parse("0 0 15 */3 *")
|
||||
//
|
||||
// // Same as above, just excludes time fields
|
||||
// subsParser := NewParser(Dom | Month | Dow)
|
||||
// sched, err := specParser.Parse("15 */3 *")
|
||||
//
|
||||
// // Same as above, just makes Dow optional
|
||||
// subsParser := NewParser(Dom | Month | DowOptional)
|
||||
// sched, err := specParser.Parse("15 */3")
|
||||
//
|
||||
func NewParser(options ParseOption) Parser {
|
||||
optionals := 0
|
||||
if options&DowOptional > 0 {
|
||||
optionals++
|
||||
}
|
||||
if options&SecondOptional > 0 {
|
||||
optionals++
|
||||
}
|
||||
if optionals > 1 {
|
||||
panic("multiple optionals may not be configured")
|
||||
}
|
||||
return Parser{options}
|
||||
}
|
||||
|
||||
// Parse returns a new crontab schedule representing the given spec.
|
||||
// It returns a descriptive error if the spec is not valid.
|
||||
// It accepts crontab specs and features configured by NewParser.
|
||||
func (p Parser) Parse(spec string) (Schedule, error) {
|
||||
if len(spec) == 0 {
|
||||
return nil, fmt.Errorf("empty spec string")
|
||||
}
|
||||
|
||||
// Extract timezone if present
|
||||
var loc = time.Local
|
||||
if strings.HasPrefix(spec, "TZ=") || strings.HasPrefix(spec, "CRON_TZ=") {
|
||||
var err error
|
||||
i := strings.Index(spec, " ")
|
||||
eq := strings.Index(spec, "=")
|
||||
if loc, err = time.LoadLocation(spec[eq+1 : i]); err != nil {
|
||||
return nil, fmt.Errorf("provided bad location %s: %v", spec[eq+1:i], err)
|
||||
}
|
||||
spec = strings.TrimSpace(spec[i:])
|
||||
}
|
||||
|
||||
// Handle named schedules (descriptors), if configured
|
||||
if strings.HasPrefix(spec, "@") {
|
||||
if p.options&Descriptor == 0 {
|
||||
return nil, fmt.Errorf("parser does not accept descriptors: %v", spec)
|
||||
}
|
||||
return parseDescriptor(spec, loc)
|
||||
}
|
||||
|
||||
// Split on whitespace.
|
||||
fields := strings.Fields(spec)
|
||||
|
||||
// Validate & fill in any omitted or optional fields
|
||||
var err error
|
||||
fields, err = normalizeFields(fields, p.options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
field := func(field string, r bounds) uint64 {
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
var bits uint64
|
||||
bits, err = getField(field, r)
|
||||
return bits
|
||||
}
|
||||
|
||||
var (
|
||||
second = field(fields[0], seconds)
|
||||
minute = field(fields[1], minutes)
|
||||
hour = field(fields[2], hours)
|
||||
dayofmonth = field(fields[3], dom)
|
||||
month = field(fields[4], months)
|
||||
dayofweek = field(fields[5], dow)
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &SpecSchedule{
|
||||
Second: second,
|
||||
Minute: minute,
|
||||
Hour: hour,
|
||||
Dom: dayofmonth,
|
||||
Month: month,
|
||||
Dow: dayofweek,
|
||||
Location: loc,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// normalizeFields takes a subset set of the time fields and returns the full set
|
||||
// with defaults (zeroes) populated for unset fields.
|
||||
//
|
||||
// As part of performing this function, it also validates that the provided
|
||||
// fields are compatible with the configured options.
|
||||
func normalizeFields(fields []string, options ParseOption) ([]string, error) {
|
||||
// Validate optionals & add their field to options
|
||||
optionals := 0
|
||||
if options&SecondOptional > 0 {
|
||||
options |= Second
|
||||
optionals++
|
||||
}
|
||||
if options&DowOptional > 0 {
|
||||
options |= Dow
|
||||
optionals++
|
||||
}
|
||||
if optionals > 1 {
|
||||
return nil, fmt.Errorf("multiple optionals may not be configured")
|
||||
}
|
||||
|
||||
// Figure out how many fields we need
|
||||
max := 0
|
||||
for _, place := range places {
|
||||
if options&place > 0 {
|
||||
max++
|
||||
}
|
||||
}
|
||||
min := max - optionals
|
||||
|
||||
// Validate number of fields
|
||||
if count := len(fields); count < min || count > max {
|
||||
if min == max {
|
||||
return nil, fmt.Errorf("expected exactly %d fields, found %d: %s", min, count, fields)
|
||||
}
|
||||
return nil, fmt.Errorf("expected %d to %d fields, found %d: %s", min, max, count, fields)
|
||||
}
|
||||
|
||||
// Populate the optional field if not provided
|
||||
if min < max && len(fields) == min {
|
||||
switch {
|
||||
case options&DowOptional > 0:
|
||||
fields = append(fields, defaults[5]) // TODO: improve access to default
|
||||
case options&SecondOptional > 0:
|
||||
fields = append([]string{defaults[0]}, fields...)
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown optional field")
|
||||
}
|
||||
}
|
||||
|
||||
// Populate all fields not part of options with their defaults
|
||||
n := 0
|
||||
expandedFields := make([]string, len(places))
|
||||
copy(expandedFields, defaults)
|
||||
for i, place := range places {
|
||||
if options&place > 0 {
|
||||
expandedFields[i] = fields[n]
|
||||
n++
|
||||
}
|
||||
}
|
||||
return expandedFields, nil
|
||||
}
|
||||
|
||||
var standardParser = NewParser(
|
||||
Minute | Hour | Dom | Month | Dow | Descriptor,
|
||||
)
|
||||
|
||||
// ParseStandard returns a new crontab schedule representing the given
|
||||
// standardSpec (https://en.wikipedia.org/wiki/Cron). It requires 5 entries
|
||||
// representing: minute, hour, day of month, month and day of week, in that
|
||||
// order. It returns a descriptive error if the spec is not valid.
|
||||
//
|
||||
// It accepts
|
||||
// - Standard crontab specs, e.g. "* * * * ?"
|
||||
// - Descriptors, e.g. "@midnight", "@every 1h30m"
|
||||
func ParseStandard(standardSpec string) (Schedule, error) {
|
||||
return standardParser.Parse(standardSpec)
|
||||
}
|
||||
|
||||
// getField returns an Int with the bits set representing all of the times that
|
||||
// the field represents or error parsing field value. A "field" is a comma-separated
|
||||
// list of "ranges".
|
||||
func getField(field string, r bounds) (uint64, error) {
|
||||
var bits uint64
|
||||
ranges := strings.FieldsFunc(field, func(r rune) bool { return r == ',' })
|
||||
for _, expr := range ranges {
|
||||
bit, err := getRange(expr, r)
|
||||
if err != nil {
|
||||
return bits, err
|
||||
}
|
||||
bits |= bit
|
||||
}
|
||||
return bits, nil
|
||||
}
|
||||
|
||||
// getRange returns the bits indicated by the given expression:
|
||||
// number | number "-" number [ "/" number ]
|
||||
// or error parsing range.
|
||||
func getRange(expr string, r bounds) (uint64, error) {
|
||||
var (
|
||||
start, end, step uint
|
||||
rangeAndStep = strings.Split(expr, "/")
|
||||
lowAndHigh = strings.Split(rangeAndStep[0], "-")
|
||||
singleDigit = len(lowAndHigh) == 1
|
||||
err error
|
||||
)
|
||||
|
||||
var extra uint64
|
||||
if lowAndHigh[0] == "*" || lowAndHigh[0] == "?" {
|
||||
start = r.min
|
||||
end = r.max
|
||||
extra = starBit
|
||||
} else {
|
||||
start, err = parseIntOrName(lowAndHigh[0], r.names)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
switch len(lowAndHigh) {
|
||||
case 1:
|
||||
end = start
|
||||
case 2:
|
||||
end, err = parseIntOrName(lowAndHigh[1], r.names)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
default:
|
||||
return 0, fmt.Errorf("too many hyphens: %s", expr)
|
||||
}
|
||||
}
|
||||
|
||||
switch len(rangeAndStep) {
|
||||
case 1:
|
||||
step = 1
|
||||
case 2:
|
||||
step, err = mustParseInt(rangeAndStep[1])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// Special handling: "N/step" means "N-max/step".
|
||||
if singleDigit {
|
||||
end = r.max
|
||||
}
|
||||
if step > 1 {
|
||||
extra = 0
|
||||
}
|
||||
default:
|
||||
return 0, fmt.Errorf("too many slashes: %s", expr)
|
||||
}
|
||||
|
||||
if start < r.min {
|
||||
return 0, fmt.Errorf("beginning of range (%d) below minimum (%d): %s", start, r.min, expr)
|
||||
}
|
||||
if end > r.max {
|
||||
return 0, fmt.Errorf("end of range (%d) above maximum (%d): %s", end, r.max, expr)
|
||||
}
|
||||
if start > end {
|
||||
return 0, fmt.Errorf("beginning of range (%d) beyond end of range (%d): %s", start, end, expr)
|
||||
}
|
||||
if step == 0 {
|
||||
return 0, fmt.Errorf("step of range should be a positive number: %s", expr)
|
||||
}
|
||||
|
||||
return getBits(start, end, step) | extra, nil
|
||||
}
|
||||
|
||||
// parseIntOrName returns the (possibly-named) integer contained in expr.
|
||||
func parseIntOrName(expr string, names map[string]uint) (uint, error) {
|
||||
if names != nil {
|
||||
if namedInt, ok := names[strings.ToLower(expr)]; ok {
|
||||
return namedInt, nil
|
||||
}
|
||||
}
|
||||
return mustParseInt(expr)
|
||||
}
|
||||
|
||||
// mustParseInt parses the given expression as an int or returns an error.
|
||||
func mustParseInt(expr string) (uint, error) {
|
||||
num, err := strconv.Atoi(expr)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("failed to parse int from %s: %s", expr, err)
|
||||
}
|
||||
if num < 0 {
|
||||
return 0, fmt.Errorf("negative number (%d) not allowed: %s", num, expr)
|
||||
}
|
||||
|
||||
return uint(num), nil
|
||||
}
|
||||
|
||||
// getBits sets all bits in the range [min, max], modulo the given step size.
|
||||
func getBits(min, max, step uint) uint64 {
|
||||
var bits uint64
|
||||
|
||||
// If step is 1, use shifts.
|
||||
if step == 1 {
|
||||
return ^(math.MaxUint64 << (max + 1)) & (math.MaxUint64 << min)
|
||||
}
|
||||
|
||||
// Else, use a simple loop.
|
||||
for i := min; i <= max; i += step {
|
||||
bits |= 1 << i
|
||||
}
|
||||
return bits
|
||||
}
|
||||
|
||||
// all returns all bits within the given bounds. (plus the star bit)
|
||||
func all(r bounds) uint64 {
|
||||
return getBits(r.min, r.max, 1) | starBit
|
||||
}
|
||||
|
||||
// parseDescriptor returns a predefined schedule for the expression, or error if none matches.
|
||||
func parseDescriptor(descriptor string, loc *time.Location) (Schedule, error) {
|
||||
switch descriptor {
|
||||
case "@yearly", "@annually":
|
||||
return &SpecSchedule{
|
||||
Second: 1 << seconds.min,
|
||||
Minute: 1 << minutes.min,
|
||||
Hour: 1 << hours.min,
|
||||
Dom: 1 << dom.min,
|
||||
Month: 1 << months.min,
|
||||
Dow: all(dow),
|
||||
Location: loc,
|
||||
}, nil
|
||||
|
||||
case "@monthly":
|
||||
return &SpecSchedule{
|
||||
Second: 1 << seconds.min,
|
||||
Minute: 1 << minutes.min,
|
||||
Hour: 1 << hours.min,
|
||||
Dom: 1 << dom.min,
|
||||
Month: all(months),
|
||||
Dow: all(dow),
|
||||
Location: loc,
|
||||
}, nil
|
||||
|
||||
case "@weekly":
|
||||
return &SpecSchedule{
|
||||
Second: 1 << seconds.min,
|
||||
Minute: 1 << minutes.min,
|
||||
Hour: 1 << hours.min,
|
||||
Dom: all(dom),
|
||||
Month: all(months),
|
||||
Dow: 1 << dow.min,
|
||||
Location: loc,
|
||||
}, nil
|
||||
|
||||
case "@daily", "@midnight":
|
||||
return &SpecSchedule{
|
||||
Second: 1 << seconds.min,
|
||||
Minute: 1 << minutes.min,
|
||||
Hour: 1 << hours.min,
|
||||
Dom: all(dom),
|
||||
Month: all(months),
|
||||
Dow: all(dow),
|
||||
Location: loc,
|
||||
}, nil
|
||||
|
||||
case "@hourly":
|
||||
return &SpecSchedule{
|
||||
Second: 1 << seconds.min,
|
||||
Minute: 1 << minutes.min,
|
||||
Hour: all(hours),
|
||||
Dom: all(dom),
|
||||
Month: all(months),
|
||||
Dow: all(dow),
|
||||
Location: loc,
|
||||
}, nil
|
||||
|
||||
}
|
||||
|
||||
const every = "@every "
|
||||
if strings.HasPrefix(descriptor, every) {
|
||||
duration, err := time.ParseDuration(descriptor[len(every):])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse duration %s: %s", descriptor, err)
|
||||
}
|
||||
return Every(duration), nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("unrecognized descriptor: %s", descriptor)
|
||||
}
|
||||
@ -1,383 +0,0 @@
|
||||
package cron
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var secondParser = NewParser(Second | Minute | Hour | Dom | Month | DowOptional | Descriptor)
|
||||
|
||||
func TestRange(t *testing.T) {
|
||||
zero := uint64(0)
|
||||
ranges := []struct {
|
||||
expr string
|
||||
min, max uint
|
||||
expected uint64
|
||||
err string
|
||||
}{
|
||||
{"5", 0, 7, 1 << 5, ""},
|
||||
{"0", 0, 7, 1 << 0, ""},
|
||||
{"7", 0, 7, 1 << 7, ""},
|
||||
|
||||
{"5-5", 0, 7, 1 << 5, ""},
|
||||
{"5-6", 0, 7, 1<<5 | 1<<6, ""},
|
||||
{"5-7", 0, 7, 1<<5 | 1<<6 | 1<<7, ""},
|
||||
|
||||
{"5-6/2", 0, 7, 1 << 5, ""},
|
||||
{"5-7/2", 0, 7, 1<<5 | 1<<7, ""},
|
||||
{"5-7/1", 0, 7, 1<<5 | 1<<6 | 1<<7, ""},
|
||||
|
||||
{"*", 1, 3, 1<<1 | 1<<2 | 1<<3 | starBit, ""},
|
||||
{"*/2", 1, 3, 1<<1 | 1<<3, ""},
|
||||
|
||||
{"5--5", 0, 0, zero, "too many hyphens"},
|
||||
{"jan-x", 0, 0, zero, "failed to parse int from"},
|
||||
{"2-x", 1, 5, zero, "failed to parse int from"},
|
||||
{"*/-12", 0, 0, zero, "negative number"},
|
||||
{"*//2", 0, 0, zero, "too many slashes"},
|
||||
{"1", 3, 5, zero, "below minimum"},
|
||||
{"6", 3, 5, zero, "above maximum"},
|
||||
{"5-3", 3, 5, zero, "beyond end of range"},
|
||||
{"*/0", 0, 0, zero, "should be a positive number"},
|
||||
}
|
||||
|
||||
for _, c := range ranges {
|
||||
actual, err := getRange(c.expr, bounds{c.min, c.max, nil})
|
||||
if len(c.err) != 0 && (err == nil || !strings.Contains(err.Error(), c.err)) {
|
||||
t.Errorf("%s => expected %v, got %v", c.expr, c.err, err)
|
||||
}
|
||||
if len(c.err) == 0 && err != nil {
|
||||
t.Errorf("%s => unexpected error %v", c.expr, err)
|
||||
}
|
||||
if actual != c.expected {
|
||||
t.Errorf("%s => expected %d, got %d", c.expr, c.expected, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestField(t *testing.T) {
|
||||
fields := []struct {
|
||||
expr string
|
||||
min, max uint
|
||||
expected uint64
|
||||
}{
|
||||
{"5", 1, 7, 1 << 5},
|
||||
{"5,6", 1, 7, 1<<5 | 1<<6},
|
||||
{"5,6,7", 1, 7, 1<<5 | 1<<6 | 1<<7},
|
||||
{"1,5-7/2,3", 1, 7, 1<<1 | 1<<5 | 1<<7 | 1<<3},
|
||||
}
|
||||
|
||||
for _, c := range fields {
|
||||
actual, _ := getField(c.expr, bounds{c.min, c.max, nil})
|
||||
if actual != c.expected {
|
||||
t.Errorf("%s => expected %d, got %d", c.expr, c.expected, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAll(t *testing.T) {
|
||||
allBits := []struct {
|
||||
r bounds
|
||||
expected uint64
|
||||
}{
|
||||
{minutes, 0xfffffffffffffff}, // 0-59: 60 ones
|
||||
{hours, 0xffffff}, // 0-23: 24 ones
|
||||
{dom, 0xfffffffe}, // 1-31: 31 ones, 1 zero
|
||||
{months, 0x1ffe}, // 1-12: 12 ones, 1 zero
|
||||
{dow, 0x7f}, // 0-6: 7 ones
|
||||
}
|
||||
|
||||
for _, c := range allBits {
|
||||
actual := all(c.r) // all() adds the starBit, so compensate for that..
|
||||
if c.expected|starBit != actual {
|
||||
t.Errorf("%d-%d/%d => expected %b, got %b",
|
||||
c.r.min, c.r.max, 1, c.expected|starBit, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBits(t *testing.T) {
|
||||
bits := []struct {
|
||||
min, max, step uint
|
||||
expected uint64
|
||||
}{
|
||||
{0, 0, 1, 0x1},
|
||||
{1, 1, 1, 0x2},
|
||||
{1, 5, 2, 0x2a}, // 101010
|
||||
{1, 4, 2, 0xa}, // 1010
|
||||
}
|
||||
|
||||
for _, c := range bits {
|
||||
actual := getBits(c.min, c.max, c.step)
|
||||
if c.expected != actual {
|
||||
t.Errorf("%d-%d/%d => expected %b, got %b",
|
||||
c.min, c.max, c.step, c.expected, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseScheduleErrors(t *testing.T) {
|
||||
var tests = []struct{ expr, err string }{
|
||||
{"* 5 j * * *", "failed to parse int from"},
|
||||
{"@every Xm", "failed to parse duration"},
|
||||
{"@unrecognized", "unrecognized descriptor"},
|
||||
{"* * * *", "expected 5 to 6 fields"},
|
||||
{"", "empty spec string"},
|
||||
}
|
||||
for _, c := range tests {
|
||||
actual, err := secondParser.Parse(c.expr)
|
||||
if err == nil || !strings.Contains(err.Error(), c.err) {
|
||||
t.Errorf("%s => expected %v, got %v", c.expr, c.err, err)
|
||||
}
|
||||
if actual != nil {
|
||||
t.Errorf("expected nil schedule on error, got %v", actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseSchedule(t *testing.T) {
|
||||
tokyo, _ := time.LoadLocation("Asia/Tokyo")
|
||||
entries := []struct {
|
||||
parser Parser
|
||||
expr string
|
||||
expected Schedule
|
||||
}{
|
||||
{secondParser, "0 5 * * * *", every5min(time.Local)},
|
||||
{standardParser, "5 * * * *", every5min(time.Local)},
|
||||
{secondParser, "CRON_TZ=UTC 0 5 * * * *", every5min(time.UTC)},
|
||||
{standardParser, "CRON_TZ=UTC 5 * * * *", every5min(time.UTC)},
|
||||
{secondParser, "CRON_TZ=Asia/Tokyo 0 5 * * * *", every5min(tokyo)},
|
||||
{secondParser, "@every 5m", ConstantDelaySchedule{5 * time.Minute}},
|
||||
{secondParser, "@midnight", midnight(time.Local)},
|
||||
{secondParser, "TZ=UTC @midnight", midnight(time.UTC)},
|
||||
{secondParser, "TZ=Asia/Tokyo @midnight", midnight(tokyo)},
|
||||
{secondParser, "@yearly", annual(time.Local)},
|
||||
{secondParser, "@annually", annual(time.Local)},
|
||||
{
|
||||
parser: secondParser,
|
||||
expr: "* 5 * * * *",
|
||||
expected: &SpecSchedule{
|
||||
Second: all(seconds),
|
||||
Minute: 1 << 5,
|
||||
Hour: all(hours),
|
||||
Dom: all(dom),
|
||||
Month: all(months),
|
||||
Dow: all(dow),
|
||||
Location: time.Local,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range entries {
|
||||
actual, err := c.parser.Parse(c.expr)
|
||||
if err != nil {
|
||||
t.Errorf("%s => unexpected error %v", c.expr, err)
|
||||
}
|
||||
if !reflect.DeepEqual(actual, c.expected) {
|
||||
t.Errorf("%s => expected %b, got %b", c.expr, c.expected, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestOptionalSecondSchedule(t *testing.T) {
|
||||
parser := NewParser(SecondOptional | Minute | Hour | Dom | Month | Dow | Descriptor)
|
||||
entries := []struct {
|
||||
expr string
|
||||
expected Schedule
|
||||
}{
|
||||
{"0 5 * * * *", every5min(time.Local)},
|
||||
{"5 5 * * * *", every5min5s(time.Local)},
|
||||
{"5 * * * *", every5min(time.Local)},
|
||||
}
|
||||
|
||||
for _, c := range entries {
|
||||
actual, err := parser.Parse(c.expr)
|
||||
if err != nil {
|
||||
t.Errorf("%s => unexpected error %v", c.expr, err)
|
||||
}
|
||||
if !reflect.DeepEqual(actual, c.expected) {
|
||||
t.Errorf("%s => expected %b, got %b", c.expr, c.expected, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNormalizeFields(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input []string
|
||||
options ParseOption
|
||||
expected []string
|
||||
}{
|
||||
{
|
||||
"AllFields_NoOptional",
|
||||
[]string{"0", "5", "*", "*", "*", "*"},
|
||||
Second | Minute | Hour | Dom | Month | Dow | Descriptor,
|
||||
[]string{"0", "5", "*", "*", "*", "*"},
|
||||
},
|
||||
{
|
||||
"AllFields_SecondOptional_Provided",
|
||||
[]string{"0", "5", "*", "*", "*", "*"},
|
||||
SecondOptional | Minute | Hour | Dom | Month | Dow | Descriptor,
|
||||
[]string{"0", "5", "*", "*", "*", "*"},
|
||||
},
|
||||
{
|
||||
"AllFields_SecondOptional_NotProvided",
|
||||
[]string{"5", "*", "*", "*", "*"},
|
||||
SecondOptional | Minute | Hour | Dom | Month | Dow | Descriptor,
|
||||
[]string{"0", "5", "*", "*", "*", "*"},
|
||||
},
|
||||
{
|
||||
"SubsetFields_NoOptional",
|
||||
[]string{"5", "15", "*"},
|
||||
Hour | Dom | Month,
|
||||
[]string{"0", "0", "5", "15", "*", "*"},
|
||||
},
|
||||
{
|
||||
"SubsetFields_DowOptional_Provided",
|
||||
[]string{"5", "15", "*", "4"},
|
||||
Hour | Dom | Month | DowOptional,
|
||||
[]string{"0", "0", "5", "15", "*", "4"},
|
||||
},
|
||||
{
|
||||
"SubsetFields_DowOptional_NotProvided",
|
||||
[]string{"5", "15", "*"},
|
||||
Hour | Dom | Month | DowOptional,
|
||||
[]string{"0", "0", "5", "15", "*", "*"},
|
||||
},
|
||||
{
|
||||
"SubsetFields_SecondOptional_NotProvided",
|
||||
[]string{"5", "15", "*"},
|
||||
SecondOptional | Hour | Dom | Month,
|
||||
[]string{"0", "0", "5", "15", "*", "*"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
actual, err := normalizeFields(test.input, test.options)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(actual, test.expected) {
|
||||
t.Errorf("expected %v, got %v", test.expected, actual)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNormalizeFields_Errors(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input []string
|
||||
options ParseOption
|
||||
err string
|
||||
}{
|
||||
{
|
||||
"TwoOptionals",
|
||||
[]string{"0", "5", "*", "*", "*", "*"},
|
||||
SecondOptional | Minute | Hour | Dom | Month | DowOptional,
|
||||
"",
|
||||
},
|
||||
{
|
||||
"TooManyFields",
|
||||
[]string{"0", "5", "*", "*"},
|
||||
SecondOptional | Minute | Hour,
|
||||
"",
|
||||
},
|
||||
{
|
||||
"NoFields",
|
||||
[]string{},
|
||||
SecondOptional | Minute | Hour,
|
||||
"",
|
||||
},
|
||||
{
|
||||
"TooFewFields",
|
||||
[]string{"*"},
|
||||
SecondOptional | Minute | Hour,
|
||||
"",
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
actual, err := normalizeFields(test.input, test.options)
|
||||
if err == nil {
|
||||
t.Errorf("expected an error, got none. results: %v", actual)
|
||||
}
|
||||
if !strings.Contains(err.Error(), test.err) {
|
||||
t.Errorf("expected error %q, got %q", test.err, err.Error())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestStandardSpecSchedule(t *testing.T) {
|
||||
entries := []struct {
|
||||
expr string
|
||||
expected Schedule
|
||||
err string
|
||||
}{
|
||||
{
|
||||
expr: "5 * * * *",
|
||||
expected: &SpecSchedule{1 << seconds.min, 1 << 5, all(hours), all(dom), all(months), all(dow), time.Local},
|
||||
},
|
||||
{
|
||||
expr: "@every 5m",
|
||||
expected: ConstantDelaySchedule{time.Duration(5) * time.Minute},
|
||||
},
|
||||
{
|
||||
expr: "5 j * * *",
|
||||
err: "failed to parse int from",
|
||||
},
|
||||
{
|
||||
expr: "* * * *",
|
||||
err: "expected exactly 5 fields",
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range entries {
|
||||
actual, err := ParseStandard(c.expr)
|
||||
if len(c.err) != 0 && (err == nil || !strings.Contains(err.Error(), c.err)) {
|
||||
t.Errorf("%s => expected %v, got %v", c.expr, c.err, err)
|
||||
}
|
||||
if len(c.err) == 0 && err != nil {
|
||||
t.Errorf("%s => unexpected error %v", c.expr, err)
|
||||
}
|
||||
if !reflect.DeepEqual(actual, c.expected) {
|
||||
t.Errorf("%s => expected %b, got %b", c.expr, c.expected, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNoDescriptorParser(t *testing.T) {
|
||||
parser := NewParser(Minute | Hour)
|
||||
_, err := parser.Parse("@every 1m")
|
||||
if err == nil {
|
||||
t.Error("expected an error, got none")
|
||||
}
|
||||
}
|
||||
|
||||
func every5min(loc *time.Location) *SpecSchedule {
|
||||
return &SpecSchedule{1 << 0, 1 << 5, all(hours), all(dom), all(months), all(dow), loc}
|
||||
}
|
||||
|
||||
func every5min5s(loc *time.Location) *SpecSchedule {
|
||||
return &SpecSchedule{1 << 5, 1 << 5, all(hours), all(dom), all(months), all(dow), loc}
|
||||
}
|
||||
|
||||
func midnight(loc *time.Location) *SpecSchedule {
|
||||
return &SpecSchedule{1, 1, 1, all(dom), all(months), all(dow), loc}
|
||||
}
|
||||
|
||||
func annual(loc *time.Location) *SpecSchedule {
|
||||
return &SpecSchedule{
|
||||
Second: 1 << seconds.min,
|
||||
Minute: 1 << minutes.min,
|
||||
Hour: 1 << hours.min,
|
||||
Dom: 1 << dom.min,
|
||||
Month: 1 << months.min,
|
||||
Dow: all(dow),
|
||||
Location: loc,
|
||||
}
|
||||
}
|
||||
@ -1,188 +0,0 @@
|
||||
package cron
|
||||
|
||||
import "time"
|
||||
|
||||
// SpecSchedule specifies a duty cycle (to the second granularity), based on a
|
||||
// traditional crontab specification. It is computed initially and stored as bit sets.
|
||||
type SpecSchedule struct {
|
||||
Second, Minute, Hour, Dom, Month, Dow uint64
|
||||
|
||||
// Override location for this schedule.
|
||||
Location *time.Location
|
||||
}
|
||||
|
||||
// bounds provides a range of acceptable values (plus a map of name to value).
|
||||
type bounds struct {
|
||||
min, max uint
|
||||
names map[string]uint
|
||||
}
|
||||
|
||||
// The bounds for each field.
|
||||
var (
|
||||
seconds = bounds{0, 59, nil}
|
||||
minutes = bounds{0, 59, nil}
|
||||
hours = bounds{0, 23, nil}
|
||||
dom = bounds{1, 31, nil}
|
||||
months = bounds{1, 12, map[string]uint{
|
||||
"jan": 1,
|
||||
"feb": 2,
|
||||
"mar": 3,
|
||||
"apr": 4,
|
||||
"may": 5,
|
||||
"jun": 6,
|
||||
"jul": 7,
|
||||
"aug": 8,
|
||||
"sep": 9,
|
||||
"oct": 10,
|
||||
"nov": 11,
|
||||
"dec": 12,
|
||||
}}
|
||||
dow = bounds{0, 6, map[string]uint{
|
||||
"sun": 0,
|
||||
"mon": 1,
|
||||
"tue": 2,
|
||||
"wed": 3,
|
||||
"thu": 4,
|
||||
"fri": 5,
|
||||
"sat": 6,
|
||||
}}
|
||||
)
|
||||
|
||||
const (
|
||||
// Set the top bit if a star was included in the expression.
|
||||
starBit = 1 << 63
|
||||
)
|
||||
|
||||
// Next returns the next time this schedule is activated, greater than the given
|
||||
// time. If no time can be found to satisfy the schedule, return the zero time.
|
||||
func (s *SpecSchedule) Next(t time.Time) time.Time {
|
||||
// General approach
|
||||
//
|
||||
// For Month, Day, Hour, Minute, Second:
|
||||
// Check if the time value matches. If yes, continue to the next field.
|
||||
// If the field doesn't match the schedule, then increment the field until it matches.
|
||||
// While incrementing the field, a wrap-around brings it back to the beginning
|
||||
// of the field list (since it is necessary to re-verify previous field
|
||||
// values)
|
||||
|
||||
// Convert the given time into the schedule's timezone, if one is specified.
|
||||
// Save the original timezone so we can convert back after we find a time.
|
||||
// Note that schedules without a time zone specified (time.Local) are treated
|
||||
// as local to the time provided.
|
||||
origLocation := t.Location()
|
||||
loc := s.Location
|
||||
if loc == time.Local {
|
||||
loc = t.Location()
|
||||
}
|
||||
if s.Location != time.Local {
|
||||
t = t.In(s.Location)
|
||||
}
|
||||
|
||||
// Start at the earliest possible time (the upcoming second).
|
||||
t = t.Add(1*time.Second - time.Duration(t.Nanosecond())*time.Nanosecond)
|
||||
|
||||
// This flag indicates whether a field has been incremented.
|
||||
added := false
|
||||
|
||||
// If no time is found within five years, return zero.
|
||||
yearLimit := t.Year() + 5
|
||||
|
||||
WRAP:
|
||||
if t.Year() > yearLimit {
|
||||
return time.Time{}
|
||||
}
|
||||
|
||||
// Find the first applicable month.
|
||||
// If it's this month, then do nothing.
|
||||
for 1<<uint(t.Month())&s.Month == 0 {
|
||||
// If we have to add a month, reset the other parts to 0.
|
||||
if !added {
|
||||
added = true
|
||||
// Otherwise, set the date at the beginning (since the current time is irrelevant).
|
||||
t = time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, loc)
|
||||
}
|
||||
t = t.AddDate(0, 1, 0)
|
||||
|
||||
// Wrapped around.
|
||||
if t.Month() == time.January {
|
||||
goto WRAP
|
||||
}
|
||||
}
|
||||
|
||||
// Now get a day in that month.
|
||||
//
|
||||
// NOTE: This causes issues for daylight savings regimes where midnight does
|
||||
// not exist. For example: Sao Paulo has DST that transforms midnight on
|
||||
// 11/3 into 1am. Handle that by noticing when the Hour ends up != 0.
|
||||
for !dayMatches(s, t) {
|
||||
if !added {
|
||||
added = true
|
||||
t = time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, loc)
|
||||
}
|
||||
t = t.AddDate(0, 0, 1)
|
||||
// Notice if the hour is no longer midnight due to DST.
|
||||
// Add an hour if it's 23, subtract an hour if it's 1.
|
||||
if t.Hour() != 0 {
|
||||
if t.Hour() > 12 {
|
||||
t = t.Add(time.Duration(24-t.Hour()) * time.Hour)
|
||||
} else {
|
||||
t = t.Add(time.Duration(-t.Hour()) * time.Hour)
|
||||
}
|
||||
}
|
||||
|
||||
if t.Day() == 1 {
|
||||
goto WRAP
|
||||
}
|
||||
}
|
||||
|
||||
for 1<<uint(t.Hour())&s.Hour == 0 {
|
||||
if !added {
|
||||
added = true
|
||||
t = time.Date(t.Year(), t.Month(), t.Day(), t.Hour(), 0, 0, 0, loc)
|
||||
}
|
||||
t = t.Add(1 * time.Hour)
|
||||
|
||||
if t.Hour() == 0 {
|
||||
goto WRAP
|
||||
}
|
||||
}
|
||||
|
||||
for 1<<uint(t.Minute())&s.Minute == 0 {
|
||||
if !added {
|
||||
added = true
|
||||
t = t.Truncate(time.Minute)
|
||||
}
|
||||
t = t.Add(1 * time.Minute)
|
||||
|
||||
if t.Minute() == 0 {
|
||||
goto WRAP
|
||||
}
|
||||
}
|
||||
|
||||
for 1<<uint(t.Second())&s.Second == 0 {
|
||||
if !added {
|
||||
added = true
|
||||
t = t.Truncate(time.Second)
|
||||
}
|
||||
t = t.Add(1 * time.Second)
|
||||
|
||||
if t.Second() == 0 {
|
||||
goto WRAP
|
||||
}
|
||||
}
|
||||
|
||||
return t.In(origLocation)
|
||||
}
|
||||
|
||||
// dayMatches returns true if the schedule's day-of-week and day-of-month
|
||||
// restrictions are satisfied by the given time.
|
||||
func dayMatches(s *SpecSchedule, t time.Time) bool {
|
||||
var (
|
||||
domMatch bool = 1<<uint(t.Day())&s.Dom > 0
|
||||
dowMatch bool = 1<<uint(t.Weekday())&s.Dow > 0
|
||||
)
|
||||
if s.Dom&starBit > 0 || s.Dow&starBit > 0 {
|
||||
return domMatch && dowMatch
|
||||
}
|
||||
return domMatch || dowMatch
|
||||
}
|
||||
@ -1,300 +0,0 @@
|
||||
package cron
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestActivation(t *testing.T) {
|
||||
tests := []struct {
|
||||
time, spec string
|
||||
expected bool
|
||||
}{
|
||||
// Every fifteen minutes.
|
||||
{"Mon Jul 9 15:00 2012", "0/15 * * * *", true},
|
||||
{"Mon Jul 9 15:45 2012", "0/15 * * * *", true},
|
||||
{"Mon Jul 9 15:40 2012", "0/15 * * * *", false},
|
||||
|
||||
// Every fifteen minutes, starting at 5 minutes.
|
||||
{"Mon Jul 9 15:05 2012", "5/15 * * * *", true},
|
||||
{"Mon Jul 9 15:20 2012", "5/15 * * * *", true},
|
||||
{"Mon Jul 9 15:50 2012", "5/15 * * * *", true},
|
||||
|
||||
// Named months
|
||||
{"Sun Jul 15 15:00 2012", "0/15 * * Jul *", true},
|
||||
{"Sun Jul 15 15:00 2012", "0/15 * * Jun *", false},
|
||||
|
||||
// Everything set.
|
||||
{"Sun Jul 15 08:30 2012", "30 08 ? Jul Sun", true},
|
||||
{"Sun Jul 15 08:30 2012", "30 08 15 Jul ?", true},
|
||||
{"Mon Jul 16 08:30 2012", "30 08 ? Jul Sun", false},
|
||||
{"Mon Jul 16 08:30 2012", "30 08 15 Jul ?", false},
|
||||
|
||||
// Predefined schedules
|
||||
{"Mon Jul 9 15:00 2012", "@hourly", true},
|
||||
{"Mon Jul 9 15:04 2012", "@hourly", false},
|
||||
{"Mon Jul 9 15:00 2012", "@daily", false},
|
||||
{"Mon Jul 9 00:00 2012", "@daily", true},
|
||||
{"Mon Jul 9 00:00 2012", "@weekly", false},
|
||||
{"Sun Jul 8 00:00 2012", "@weekly", true},
|
||||
{"Sun Jul 8 01:00 2012", "@weekly", false},
|
||||
{"Sun Jul 8 00:00 2012", "@monthly", false},
|
||||
{"Sun Jul 1 00:00 2012", "@monthly", true},
|
||||
|
||||
// Test interaction of DOW and DOM.
|
||||
// If both are restricted, then only one needs to match.
|
||||
{"Sun Jul 15 00:00 2012", "* * 1,15 * Sun", true},
|
||||
{"Fri Jun 15 00:00 2012", "* * 1,15 * Sun", true},
|
||||
{"Wed Aug 1 00:00 2012", "* * 1,15 * Sun", true},
|
||||
{"Sun Jul 15 00:00 2012", "* * */10 * Sun", true}, // verifies #70
|
||||
|
||||
// However, if one has a star, then both need to match.
|
||||
{"Sun Jul 15 00:00 2012", "* * * * Mon", false},
|
||||
{"Mon Jul 9 00:00 2012", "* * 1,15 * *", false},
|
||||
{"Sun Jul 15 00:00 2012", "* * 1,15 * *", true},
|
||||
{"Sun Jul 15 00:00 2012", "* * */2 * Sun", true},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
sched, err := ParseStandard(test.spec)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
continue
|
||||
}
|
||||
actual := sched.Next(getTime(test.time).Add(-1 * time.Second))
|
||||
expected := getTime(test.time)
|
||||
if test.expected && expected != actual || !test.expected && expected == actual {
|
||||
t.Errorf("Fail evaluating %s on %s: (expected) %s != %s (actual)",
|
||||
test.spec, test.time, expected, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNext(t *testing.T) {
|
||||
runs := []struct {
|
||||
time, spec string
|
||||
expected string
|
||||
}{
|
||||
// Simple cases
|
||||
{"Mon Jul 9 14:45 2012", "0 0/15 * * * *", "Mon Jul 9 15:00 2012"},
|
||||
{"Mon Jul 9 14:59 2012", "0 0/15 * * * *", "Mon Jul 9 15:00 2012"},
|
||||
{"Mon Jul 9 14:59:59 2012", "0 0/15 * * * *", "Mon Jul 9 15:00 2012"},
|
||||
|
||||
// Wrap around hours
|
||||
{"Mon Jul 9 15:45 2012", "0 20-35/15 * * * *", "Mon Jul 9 16:20 2012"},
|
||||
|
||||
// Wrap around days
|
||||
{"Mon Jul 9 23:46 2012", "0 */15 * * * *", "Tue Jul 10 00:00 2012"},
|
||||
{"Mon Jul 9 23:45 2012", "0 20-35/15 * * * *", "Tue Jul 10 00:20 2012"},
|
||||
{"Mon Jul 9 23:35:51 2012", "15/35 20-35/15 * * * *", "Tue Jul 10 00:20:15 2012"},
|
||||
{"Mon Jul 9 23:35:51 2012", "15/35 20-35/15 1/2 * * *", "Tue Jul 10 01:20:15 2012"},
|
||||
{"Mon Jul 9 23:35:51 2012", "15/35 20-35/15 10-12 * * *", "Tue Jul 10 10:20:15 2012"},
|
||||
|
||||
{"Mon Jul 9 23:35:51 2012", "15/35 20-35/15 1/2 */2 * *", "Thu Jul 11 01:20:15 2012"},
|
||||
{"Mon Jul 9 23:35:51 2012", "15/35 20-35/15 * 9-20 * *", "Wed Jul 10 00:20:15 2012"},
|
||||
{"Mon Jul 9 23:35:51 2012", "15/35 20-35/15 * 9-20 Jul *", "Wed Jul 10 00:20:15 2012"},
|
||||
|
||||
// Wrap around months
|
||||
{"Mon Jul 9 23:35 2012", "0 0 0 9 Apr-Oct ?", "Thu Aug 9 00:00 2012"},
|
||||
{"Mon Jul 9 23:35 2012", "0 0 0 */5 Apr,Aug,Oct Mon", "Tue Aug 1 00:00 2012"},
|
||||
{"Mon Jul 9 23:35 2012", "0 0 0 */5 Oct Mon", "Mon Oct 1 00:00 2012"},
|
||||
|
||||
// Wrap around years
|
||||
{"Mon Jul 9 23:35 2012", "0 0 0 * Feb Mon", "Mon Feb 4 00:00 2013"},
|
||||
{"Mon Jul 9 23:35 2012", "0 0 0 * Feb Mon/2", "Fri Feb 1 00:00 2013"},
|
||||
|
||||
// Wrap around minute, hour, day, month, and year
|
||||
{"Mon Dec 31 23:59:45 2012", "0 * * * * *", "Tue Jan 1 00:00:00 2013"},
|
||||
|
||||
// Leap year
|
||||
{"Mon Jul 9 23:35 2012", "0 0 0 29 Feb ?", "Mon Feb 29 00:00 2016"},
|
||||
|
||||
// Daylight savings time 2am EST (-5) -> 3am EDT (-4)
|
||||
{"2012-03-11T00:00:00-0500", "TZ=America/New_York 0 30 2 11 Mar ?", "2013-03-11T02:30:00-0400"},
|
||||
|
||||
// hourly job
|
||||
{"2012-03-11T00:00:00-0500", "TZ=America/New_York 0 0 * * * ?", "2012-03-11T01:00:00-0500"},
|
||||
{"2012-03-11T01:00:00-0500", "TZ=America/New_York 0 0 * * * ?", "2012-03-11T03:00:00-0400"},
|
||||
{"2012-03-11T03:00:00-0400", "TZ=America/New_York 0 0 * * * ?", "2012-03-11T04:00:00-0400"},
|
||||
{"2012-03-11T04:00:00-0400", "TZ=America/New_York 0 0 * * * ?", "2012-03-11T05:00:00-0400"},
|
||||
|
||||
// hourly job using CRON_TZ
|
||||
{"2012-03-11T00:00:00-0500", "CRON_TZ=America/New_York 0 0 * * * ?", "2012-03-11T01:00:00-0500"},
|
||||
{"2012-03-11T01:00:00-0500", "CRON_TZ=America/New_York 0 0 * * * ?", "2012-03-11T03:00:00-0400"},
|
||||
{"2012-03-11T03:00:00-0400", "CRON_TZ=America/New_York 0 0 * * * ?", "2012-03-11T04:00:00-0400"},
|
||||
{"2012-03-11T04:00:00-0400", "CRON_TZ=America/New_York 0 0 * * * ?", "2012-03-11T05:00:00-0400"},
|
||||
|
||||
// 1am nightly job
|
||||
{"2012-03-11T00:00:00-0500", "TZ=America/New_York 0 0 1 * * ?", "2012-03-11T01:00:00-0500"},
|
||||
{"2012-03-11T01:00:00-0500", "TZ=America/New_York 0 0 1 * * ?", "2012-03-12T01:00:00-0400"},
|
||||
|
||||
// 2am nightly job (skipped)
|
||||
{"2012-03-11T00:00:00-0500", "TZ=America/New_York 0 0 2 * * ?", "2012-03-12T02:00:00-0400"},
|
||||
|
||||
// Daylight savings time 2am EDT (-4) => 1am EST (-5)
|
||||
{"2012-11-04T00:00:00-0400", "TZ=America/New_York 0 30 2 04 Nov ?", "2012-11-04T02:30:00-0500"},
|
||||
{"2012-11-04T01:45:00-0400", "TZ=America/New_York 0 30 1 04 Nov ?", "2012-11-04T01:30:00-0500"},
|
||||
|
||||
// hourly job
|
||||
{"2012-11-04T00:00:00-0400", "TZ=America/New_York 0 0 * * * ?", "2012-11-04T01:00:00-0400"},
|
||||
{"2012-11-04T01:00:00-0400", "TZ=America/New_York 0 0 * * * ?", "2012-11-04T01:00:00-0500"},
|
||||
{"2012-11-04T01:00:00-0500", "TZ=America/New_York 0 0 * * * ?", "2012-11-04T02:00:00-0500"},
|
||||
|
||||
// 1am nightly job (runs twice)
|
||||
{"2012-11-04T00:00:00-0400", "TZ=America/New_York 0 0 1 * * ?", "2012-11-04T01:00:00-0400"},
|
||||
{"2012-11-04T01:00:00-0400", "TZ=America/New_York 0 0 1 * * ?", "2012-11-04T01:00:00-0500"},
|
||||
{"2012-11-04T01:00:00-0500", "TZ=America/New_York 0 0 1 * * ?", "2012-11-05T01:00:00-0500"},
|
||||
|
||||
// 2am nightly job
|
||||
{"2012-11-04T00:00:00-0400", "TZ=America/New_York 0 0 2 * * ?", "2012-11-04T02:00:00-0500"},
|
||||
{"2012-11-04T02:00:00-0500", "TZ=America/New_York 0 0 2 * * ?", "2012-11-05T02:00:00-0500"},
|
||||
|
||||
// 3am nightly job
|
||||
{"2012-11-04T00:00:00-0400", "TZ=America/New_York 0 0 3 * * ?", "2012-11-04T03:00:00-0500"},
|
||||
{"2012-11-04T03:00:00-0500", "TZ=America/New_York 0 0 3 * * ?", "2012-11-05T03:00:00-0500"},
|
||||
|
||||
// hourly job
|
||||
{"TZ=America/New_York 2012-11-04T00:00:00-0400", "0 0 * * * ?", "2012-11-04T01:00:00-0400"},
|
||||
{"TZ=America/New_York 2012-11-04T01:00:00-0400", "0 0 * * * ?", "2012-11-04T01:00:00-0500"},
|
||||
{"TZ=America/New_York 2012-11-04T01:00:00-0500", "0 0 * * * ?", "2012-11-04T02:00:00-0500"},
|
||||
|
||||
// 1am nightly job (runs twice)
|
||||
{"TZ=America/New_York 2012-11-04T00:00:00-0400", "0 0 1 * * ?", "2012-11-04T01:00:00-0400"},
|
||||
{"TZ=America/New_York 2012-11-04T01:00:00-0400", "0 0 1 * * ?", "2012-11-04T01:00:00-0500"},
|
||||
{"TZ=America/New_York 2012-11-04T01:00:00-0500", "0 0 1 * * ?", "2012-11-05T01:00:00-0500"},
|
||||
|
||||
// 2am nightly job
|
||||
{"TZ=America/New_York 2012-11-04T00:00:00-0400", "0 0 2 * * ?", "2012-11-04T02:00:00-0500"},
|
||||
{"TZ=America/New_York 2012-11-04T02:00:00-0500", "0 0 2 * * ?", "2012-11-05T02:00:00-0500"},
|
||||
|
||||
// 3am nightly job
|
||||
{"TZ=America/New_York 2012-11-04T00:00:00-0400", "0 0 3 * * ?", "2012-11-04T03:00:00-0500"},
|
||||
{"TZ=America/New_York 2012-11-04T03:00:00-0500", "0 0 3 * * ?", "2012-11-05T03:00:00-0500"},
|
||||
|
||||
// Unsatisfiable
|
||||
{"Mon Jul 9 23:35 2012", "0 0 0 30 Feb ?", ""},
|
||||
{"Mon Jul 9 23:35 2012", "0 0 0 31 Apr ?", ""},
|
||||
|
||||
// Monthly job
|
||||
{"TZ=America/New_York 2012-11-04T00:00:00-0400", "0 0 3 3 * ?", "2012-12-03T03:00:00-0500"},
|
||||
|
||||
// Test the scenario of DST resulting in midnight not being a valid time.
|
||||
// https://github.com/robfig/cron/issues/157
|
||||
{"2018-10-17T05:00:00-0400", "TZ=America/Sao_Paulo 0 0 9 10 * ?", "2018-11-10T06:00:00-0500"},
|
||||
{"2018-02-14T05:00:00-0500", "TZ=America/Sao_Paulo 0 0 9 22 * ?", "2018-02-22T07:00:00-0500"},
|
||||
}
|
||||
|
||||
for _, c := range runs {
|
||||
sched, err := secondParser.Parse(c.spec)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
continue
|
||||
}
|
||||
actual := sched.Next(getTime(c.time))
|
||||
expected := getTime(c.expected)
|
||||
if !actual.Equal(expected) {
|
||||
t.Errorf("%s, \"%s\": (expected) %v != %v (actual)", c.time, c.spec, expected, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrors(t *testing.T) {
|
||||
invalidSpecs := []string{
|
||||
"xyz",
|
||||
"60 0 * * *",
|
||||
"0 60 * * *",
|
||||
"0 0 * * XYZ",
|
||||
}
|
||||
for _, spec := range invalidSpecs {
|
||||
_, err := ParseStandard(spec)
|
||||
if err == nil {
|
||||
t.Error("expected an error parsing: ", spec)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getTime(value string) time.Time {
|
||||
if value == "" {
|
||||
return time.Time{}
|
||||
}
|
||||
|
||||
var location = time.Local
|
||||
if strings.HasPrefix(value, "TZ=") {
|
||||
parts := strings.Fields(value)
|
||||
loc, err := time.LoadLocation(parts[0][len("TZ="):])
|
||||
if err != nil {
|
||||
panic("could not parse location:" + err.Error())
|
||||
}
|
||||
location = loc
|
||||
value = parts[1]
|
||||
}
|
||||
|
||||
var layouts = []string{
|
||||
"Mon Jan 2 15:04 2006",
|
||||
"Mon Jan 2 15:04:05 2006",
|
||||
}
|
||||
for _, layout := range layouts {
|
||||
if t, err := time.ParseInLocation(layout, value, location); err == nil {
|
||||
return t
|
||||
}
|
||||
}
|
||||
if t, err := time.ParseInLocation("2006-01-02T15:04:05-0700", value, location); err == nil {
|
||||
return t
|
||||
}
|
||||
panic("could not parse time value " + value)
|
||||
}
|
||||
|
||||
func TestNextWithTz(t *testing.T) {
|
||||
runs := []struct {
|
||||
time, spec string
|
||||
expected string
|
||||
}{
|
||||
// Failing tests
|
||||
{"2016-01-03T13:09:03+0530", "14 14 * * *", "2016-01-03T14:14:00+0530"},
|
||||
{"2016-01-03T04:09:03+0530", "14 14 * * ?", "2016-01-03T14:14:00+0530"},
|
||||
|
||||
// Passing tests
|
||||
{"2016-01-03T14:09:03+0530", "14 14 * * *", "2016-01-03T14:14:00+0530"},
|
||||
{"2016-01-03T14:00:00+0530", "14 14 * * ?", "2016-01-03T14:14:00+0530"},
|
||||
}
|
||||
for _, c := range runs {
|
||||
sched, err := ParseStandard(c.spec)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
continue
|
||||
}
|
||||
actual := sched.Next(getTimeTZ(c.time))
|
||||
expected := getTimeTZ(c.expected)
|
||||
if !actual.Equal(expected) {
|
||||
t.Errorf("%s, \"%s\": (expected) %v != %v (actual)", c.time, c.spec, expected, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getTimeTZ(value string) time.Time {
|
||||
if value == "" {
|
||||
return time.Time{}
|
||||
}
|
||||
t, err := time.Parse("Mon Jan 2 15:04 2006", value)
|
||||
if err != nil {
|
||||
t, err = time.Parse("Mon Jan 2 15:04:05 2006", value)
|
||||
if err != nil {
|
||||
t, err = time.Parse("2006-01-02T15:04:05-0700", value)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
// https://github.com/robfig/cron/issues/144
|
||||
func TestSlash0NoHang(t *testing.T) {
|
||||
schedule := "TZ=America/New_York 15/0 * * * *"
|
||||
_, err := ParseStandard(schedule)
|
||||
if err == nil {
|
||||
t.Error("expected an error on 0 increment")
|
||||
}
|
||||
}
|
||||
@ -1,38 +1,130 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
//"database/sql"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"server/GoUtil"
|
||||
"server/MergeConst"
|
||||
"server/conf"
|
||||
"server/pkg/github.com/name5566/leaf/log"
|
||||
GoUtil "server/game_util"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"gitea.bywaystudios.com/pet_home/leaf/log"
|
||||
|
||||
// "server/game"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/jmoiron/sqlx"
|
||||
)
|
||||
|
||||
type user struct {
|
||||
Id int `db:"user_id"`
|
||||
Sex int `db:"sex"`
|
||||
UserName string `db:"username"`
|
||||
Email string `db:"email"`
|
||||
var SqlDb *sqlx.DB
|
||||
var sqlDbMu sync.RWMutex
|
||||
|
||||
// GetDB 线程安全地获取数据库连接
|
||||
func GetDB() *sqlx.DB {
|
||||
sqlDbMu.RLock()
|
||||
defer sqlDbMu.RUnlock()
|
||||
return SqlDb
|
||||
}
|
||||
|
||||
var SqlDb *sqlx.DB
|
||||
// GetDBOrPanic 获取数据库连接,如果为 nil 则记录错误
|
||||
func GetDBOrPanic() *sqlx.DB {
|
||||
db := GetDB()
|
||||
if db == nil {
|
||||
log.Error("Database connection is nil, please check database initialization")
|
||||
}
|
||||
return db
|
||||
}
|
||||
|
||||
// EnsureDB 确保数据库连接可用,如果不可用则返回错误
|
||||
func EnsureDB() (*sqlx.DB, error) {
|
||||
db := GetDB()
|
||||
if db == nil {
|
||||
return nil, fmt.Errorf("database connection is nil")
|
||||
}
|
||||
if err := db.Ping(); err != nil {
|
||||
return nil, fmt.Errorf("database ping failed: %w", err)
|
||||
}
|
||||
return db, nil
|
||||
}
|
||||
|
||||
// 封装创建连接
|
||||
func connectMySQL() (*sqlx.DB, error) {
|
||||
MysqlPwd, _ := GoUtil.Decrypt(conf.Server.MySqlPwd)
|
||||
// 减少超时时间,避免长时间阻塞
|
||||
connect := fmt.Sprintf("%s:%s@(%s:%s)/%s?timeout=10s&readTimeout=15s&writeTimeout=15s&parseTime=true", conf.Server.MySqlUsr, MysqlPwd, conf.Server.MySqlAddr, conf.Server.MySqlPort, conf.Server.DbName)
|
||||
db, err := sqlx.Connect("mysql", connect)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// 增加最大连接数,减少连接等待时间
|
||||
db.SetMaxOpenConns(100)
|
||||
db.SetMaxIdleConns(20)
|
||||
db.SetConnMaxLifetime(30 * time.Minute) // 减少连接生命周期
|
||||
db.SetConnMaxIdleTime(5 * time.Minute) // 减少空闲时间
|
||||
return db, nil
|
||||
}
|
||||
|
||||
func InitDB() {
|
||||
//"用户名:密码@[连接方式](主机名:端口号)/数据库名"
|
||||
connect := fmt.Sprintf("%s:%s@(%s:%s)/%s", conf.Server.MySqlUsr, conf.Server.MySqlPwd, conf.Server.MySqlAddr, conf.Server.MySqlPort, conf.Server.DbName)
|
||||
SqlDb = sqlx.MustConnect("mysql", connect) // 设置连接数据库的参数
|
||||
SqlDb.SetMaxOpenConns(20) // 设置最大打开的连接数
|
||||
db, err := connectMySQL()
|
||||
if err != nil {
|
||||
log.Debug("connect mysql failed: %v", err)
|
||||
return
|
||||
}
|
||||
sqlDbMu.Lock()
|
||||
SqlDb = db
|
||||
sqlDbMu.Unlock()
|
||||
log.Debug("connect mysql success")
|
||||
|
||||
// 定时检测与重连
|
||||
go func() {
|
||||
ticker := time.NewTicker(5 * time.Second) // 改为5秒检测一次,降低频率
|
||||
defer ticker.Stop()
|
||||
for range ticker.C {
|
||||
sqlDbMu.RLock()
|
||||
cur := SqlDb
|
||||
sqlDbMu.RUnlock()
|
||||
|
||||
if cur == nil {
|
||||
log.Debug("mysql connection is nil, start reconnect")
|
||||
ReconnectDB()
|
||||
continue
|
||||
}
|
||||
|
||||
// Ping 操作不持有锁,避免阻塞其他操作
|
||||
if err := cur.Ping(); err != nil {
|
||||
log.Debug("mysql ping failed: %v, start reconnect", err)
|
||||
ReconnectDB()
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// 自动重连
|
||||
func ReconnectDB() {
|
||||
sqlDbMu.Lock()
|
||||
defer sqlDbMu.Unlock()
|
||||
newDb, err := connectMySQL()
|
||||
if err != nil {
|
||||
log.Debug("mysql reconnect failed: %v", err)
|
||||
return
|
||||
}
|
||||
if SqlDb != nil {
|
||||
_ = SqlDb.Close()
|
||||
}
|
||||
SqlDb = newDb
|
||||
log.Debug("mysql reconnect success")
|
||||
}
|
||||
|
||||
func SeriesTransaction(sqlstrs []string, params [][]any) (err error) {
|
||||
tx, err := SqlDb.Begin()
|
||||
sqlDb := GetDB()
|
||||
if sqlDb == nil {
|
||||
return fmt.Errorf("database connection is nil")
|
||||
}
|
||||
|
||||
tx, err := sqlDb.Begin()
|
||||
if err != nil {
|
||||
log.Debug("Transaction failed, err:%v\n", err)
|
||||
return err
|
||||
@ -60,61 +152,6 @@ func SeriesTransaction(sqlstrs []string, params [][]any) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// 更新数据
|
||||
func FormatUpdateOneAttrRow(u interface{}, tableName string, UpdateAttr string, Exclude string) (err error) {
|
||||
t := reflect.TypeOf(u)
|
||||
len1 := t.Elem().NumField()
|
||||
Fields := make([]string, len1)
|
||||
Values := make([]interface{}, len1)
|
||||
pp := reflect.ValueOf(u)
|
||||
origin := "UPDATE " + tableName + " SET "
|
||||
index := 0
|
||||
var keyValue interface{}
|
||||
for i := 0; i < len1; i++ {
|
||||
field := t.Elem().Field(i)
|
||||
if field.Tag.Get("db") != Exclude {
|
||||
if field.Tag.Get("db") == UpdateAttr {
|
||||
Fields[index] = field.Tag.Get("db") + " = ?"
|
||||
|
||||
ufield := pp.Elem().FieldByName(field.Name)
|
||||
k := ufield.Kind()
|
||||
if k == reflect.String {
|
||||
Values[index] = ufield.String()
|
||||
}
|
||||
if k == reflect.Int32 {
|
||||
Values[index] = ufield.Int()
|
||||
}
|
||||
index++
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
ufield := pp.Elem().FieldByName(field.Name)
|
||||
k := ufield.Kind()
|
||||
if k == reflect.String {
|
||||
keyValue = ufield.String()
|
||||
}
|
||||
if k == reflect.Int32 {
|
||||
keyValue = ufield.Int()
|
||||
}
|
||||
}
|
||||
}
|
||||
Values[index] = keyValue
|
||||
// Values = append(Values, keyValue)
|
||||
origin += strings.Join(Fields, ",")
|
||||
strLen := len(origin)
|
||||
origin = origin[:strLen-1]
|
||||
origin = origin + " WHERE " + Exclude + " = ?"
|
||||
sqlStr := origin
|
||||
_, err = SqlDb.Exec(sqlStr, Values...)
|
||||
if err != nil {
|
||||
log.Debug("table: %s, sql :%s, exec failed, err:%v\n", tableName, sqlStr, err)
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// "UPDATE user SET age = ?, degree = ? WHERE id = ?"
|
||||
func FormatAllMemUpdateDb(u interface{}, tableName string, Exclude string) (err error) {
|
||||
t := reflect.TypeOf(u)
|
||||
@ -145,7 +182,7 @@ func FormatAllMemUpdateDb(u interface{}, tableName string, Exclude string) (err
|
||||
if k == reflect.String {
|
||||
keyValue = ufield.String()
|
||||
}
|
||||
if k == reflect.Int32 || k == reflect.Int {
|
||||
if k == reflect.Int32 || k == reflect.Int || k == reflect.Int64 {
|
||||
keyValue = ufield.Int()
|
||||
}
|
||||
}
|
||||
@ -187,6 +224,9 @@ func FormatAllMemInsertDb(u interface{}, tableName string) (insertID int64, err
|
||||
if k == reflect.Int32 {
|
||||
Values[i] = ufield.Int()
|
||||
}
|
||||
if k == reflect.Int64 {
|
||||
Values[i] = ufield.Int()
|
||||
}
|
||||
}
|
||||
for i := range Fields {
|
||||
Fields[i] = "`" + Fields[i] + "`"
|
||||
@ -219,6 +259,28 @@ func GetPlayerBaseInfoFromDbByName(name string) *ResPlayerBaseInfo {
|
||||
return &res
|
||||
}
|
||||
|
||||
func GetPlayerBan(name string) int64 {
|
||||
sqlStr := "SELECT ban FROM t_player_baseinfo WHERE user_name = ?"
|
||||
var ban int64
|
||||
if err := SqlDb.Get(&ban, sqlStr, name); err != nil {
|
||||
log.Debug("table: %s, sql :%s, exec failed, err:%v\n", "PlayerBaseInfo", sqlStr, err)
|
||||
return 0
|
||||
}
|
||||
return ban
|
||||
}
|
||||
|
||||
func UpdatePlayerBan(uid int64, ban int64) error {
|
||||
sqlStr := "UPDATE t_player_baseinfo SET ban = ? WHERE dwUin = ?"
|
||||
_, err := SqlDb.Exec(sqlStr, ban, uid)
|
||||
return err
|
||||
}
|
||||
|
||||
func UpdatePlayerBaseInfoName(oldName, newName string) error {
|
||||
sqlStr := "UPDATE t_player_baseinfo SET user_name = ? WHERE user_name = ?"
|
||||
_, err := SqlDb.Exec(sqlStr, newName, oldName)
|
||||
return err
|
||||
}
|
||||
|
||||
func GetPlayerBaseInfoFromDbById(id int32) *ResPlayerBaseInfo {
|
||||
sqlStr := "SELECT * FROM t_player_baseinfo WHERE dwUin = ?"
|
||||
var res ResPlayerBaseInfo
|
||||
@ -233,73 +295,92 @@ func GetAccountInfoFromDb(name string) *Db_Account {
|
||||
sqlStr := "SELECT * FROM t_account WHERE user_name = ?"
|
||||
var res Db_Account
|
||||
if err := SqlDb.Get(&res, sqlStr, name); err != nil {
|
||||
log.Debug("table: %s, sql :%s, exec failed, err:%v\n", "account", sqlStr, err)
|
||||
log.Debug("登录的账号不存在:%s", name)
|
||||
return nil
|
||||
}
|
||||
return &res
|
||||
}
|
||||
|
||||
func FormatAllMemLoadDb(u interface{}, tableName string, Exclude string) (err error) {
|
||||
t := reflect.TypeOf(u)
|
||||
len := t.Elem().NumField()
|
||||
Fields := make([]string, len)
|
||||
Values := make([]interface{}, len)
|
||||
pp := reflect.ValueOf(u)
|
||||
origin := "SELECT * FROM " + tableName + " WHERE "
|
||||
index := 0
|
||||
var keyValue interface{}
|
||||
for i := 0; i < len; i++ {
|
||||
field := t.Elem().Field(i)
|
||||
if field.Tag.Get("db") != Exclude {
|
||||
Fields[index] = field.Tag.Get("db") + " = ?"
|
||||
|
||||
ufield := pp.Elem().FieldByName(field.Name)
|
||||
k := ufield.Kind()
|
||||
if k == reflect.String {
|
||||
Values[index] = ufield.String()
|
||||
}
|
||||
if k == reflect.Int32 || k == reflect.Int || k == reflect.Int64 {
|
||||
Values[index] = ufield.Int()
|
||||
}
|
||||
index++
|
||||
} else {
|
||||
|
||||
ufield := pp.Elem().FieldByName(field.Name)
|
||||
k := ufield.Kind()
|
||||
if k == reflect.String {
|
||||
keyValue = ufield.String()
|
||||
}
|
||||
if k == reflect.Int32 {
|
||||
keyValue = ufield.Int()
|
||||
}
|
||||
}
|
||||
}
|
||||
Values[index] = keyValue
|
||||
// Values = append(Values, keyValue)
|
||||
origin += strings.Join(Fields, " AND ")
|
||||
sqlStr := origin
|
||||
if err := SqlDb.Get(u, sqlStr, Values...); err != nil {
|
||||
log.Debug("table: %s, sql :%s, exec failed, err:%v\n", tableName, sqlStr, err)
|
||||
func ResetAccountData(oldName, newName string) error {
|
||||
sqlStr := "UPDATE t_account SET user_name = ? WHERE user_name = ?"
|
||||
_, err := SqlDb.Exec(sqlStr, newName, oldName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sqlStr = "UPDATE t_player_baseinfo SET user_name = ? WHERE user_name = ?"
|
||||
_, err = SqlDb.Exec(sqlStr, newName, oldName)
|
||||
return err
|
||||
}
|
||||
|
||||
func MappingAccountData(oldName, newName string) error {
|
||||
sqlStr := "UPDATE t_account SET user_name = ? WHERE user_name = ?"
|
||||
_, err := SqlDb.Exec(sqlStr, "", oldName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sqlStr = "UPDATE t_player_baseinfo SET user_name = ? WHERE user_name = ?"
|
||||
_, err = SqlDb.Exec(sqlStr, "", oldName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sqlStr = "UPDATE t_account SET user_name = ? WHERE user_name = ?"
|
||||
_, err = SqlDb.Exec(sqlStr, oldName, newName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sqlStr = "UPDATE t_player_baseinfo SET user_name = ? WHERE user_name = ?"
|
||||
_, err = SqlDb.Exec(sqlStr, oldName, newName)
|
||||
return err
|
||||
}
|
||||
|
||||
func UpdateAccountInfoToDb(account *Db_Account) (err error) {
|
||||
_, err = SqlDb.Exec("UPDATE t_account SET user_password = ? WHERE user_name = ?", account.UserPassword, account.UserName)
|
||||
return
|
||||
}
|
||||
|
||||
func UpdateAccountInfoName(account *Db_Account, newName string) (err error) {
|
||||
_, err = SqlDb.Exec("UPDATE t_account SET user_name = ? WHERE user_name = ?", newName, account.UserName)
|
||||
return
|
||||
}
|
||||
|
||||
func UpdateAccountInfoDeviceToDb(account *Db_Account) (err error) {
|
||||
_, err = SqlDb.Exec("UPDATE t_account SET device_id = ? WHERE user_name = ?", account.DeviceId, account.UserName)
|
||||
return
|
||||
}
|
||||
|
||||
func GetServerData(d interface{}, Key string) (err error) {
|
||||
sqlDb := GetDB()
|
||||
if sqlDb == nil {
|
||||
return fmt.Errorf("database connection is nil")
|
||||
}
|
||||
sql := "select * from t_server_mod where `key` = ?"
|
||||
err = SqlDb.Get(d, sql, Key)
|
||||
err = sqlDb.Get(d, sql, Key)
|
||||
return
|
||||
}
|
||||
|
||||
func SaveServerData(data *SqlServerModStruct) error {
|
||||
sqlDb := GetDB()
|
||||
if sqlDb == nil {
|
||||
return fmt.Errorf("database connection is nil")
|
||||
}
|
||||
sql := "update t_server_mod set `mData` = ? , `updateTime` = ? where `key` = ?"
|
||||
_, err := SqlDb.Exec(sql, data.ModData, data.UpdataTime, data.Key)
|
||||
_, err := sqlDb.Exec(sql, data.ModData, data.UpdataTime, data.Key)
|
||||
return err
|
||||
}
|
||||
|
||||
func SaveServerDataWithTx(tx *sql.Tx, data *SqlServerModStruct) error {
|
||||
sql := "update t_server_mod set `mData` = ? , `updateTime` = ? where `key` = ?"
|
||||
_, err := tx.Exec(sql, data.ModData, data.UpdataTime, data.Key)
|
||||
return err
|
||||
}
|
||||
|
||||
func InsertServerData(data *SqlServerModStruct) error {
|
||||
sqlDb := GetDB()
|
||||
if sqlDb == nil {
|
||||
return fmt.Errorf("database connection is nil")
|
||||
}
|
||||
sql := "insert into t_server_mod (`mData` , `updateTime` ,`key`) Values (?,?,?)"
|
||||
_, err := SqlDb.Exec(sql, data.ModData, data.UpdataTime, data.Key)
|
||||
_, err := sqlDb.Exec(sql, data.ModData, data.UpdataTime, data.Key)
|
||||
return err
|
||||
}
|
||||
|
||||
@ -327,113 +408,22 @@ func GetPlayerClientData(d interface{}, Key string) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func InsertData(u interface{}, tableName string) (insertID int64, err error) {
|
||||
t := reflect.TypeOf(u)
|
||||
len := t.Elem().NumField()
|
||||
Fields := make([]string, 0)
|
||||
Fields1 := make([]string, 0)
|
||||
Values := make([]interface{}, 0)
|
||||
pp := reflect.ValueOf(u)
|
||||
origin := "INSERT INTO " + tableName + "("
|
||||
for i := 0; i < len; i++ {
|
||||
field := t.Elem().Field(i)
|
||||
if field.Tag.Get("db") == "id" {
|
||||
continue
|
||||
}
|
||||
|
||||
ufield := pp.Elem().FieldByName(field.Name)
|
||||
k := ufield.Kind()
|
||||
if k == reflect.String && ufield.String() == "" {
|
||||
continue
|
||||
}
|
||||
if (k == reflect.Int32 || k == reflect.Int || k == reflect.Int64) && ufield.Int() == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
if k == reflect.String {
|
||||
Values = append(Values, ufield.String())
|
||||
}
|
||||
if k == reflect.Int32 || k == reflect.Int || k == reflect.Int64 {
|
||||
Values = append(Values, ufield.Int())
|
||||
}
|
||||
Fields = append(Fields, field.Tag.Get("db"))
|
||||
Fields1 = append(Fields1, "?")
|
||||
}
|
||||
for i := range Fields {
|
||||
Fields[i] = "`" + Fields[i] + "`"
|
||||
}
|
||||
origin += strings.Join(Fields, ",")
|
||||
origin += ") VALUES("
|
||||
origin += strings.Join(Fields1, ",")
|
||||
origin += ")"
|
||||
sqlStr := origin
|
||||
result, err := SqlDb.Exec(sqlStr, Values...)
|
||||
if err != nil {
|
||||
log.Debug("InsertData exec failed, sql : %s ;err:%v\n", sqlStr, err)
|
||||
return
|
||||
}
|
||||
insertID, err = result.LastInsertId()
|
||||
if err != nil {
|
||||
log.Debug("InsertData exec failed, err:%v\n", err)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func UpdateData(u interface{}, tableName string, Exclude string) (err error) {
|
||||
t := reflect.TypeOf(u)
|
||||
len1 := t.Elem().NumField()
|
||||
Fields := make([]string, 0)
|
||||
Values := make([]interface{}, 0)
|
||||
pp := reflect.ValueOf(u)
|
||||
origin := "UPDATE " + tableName + " SET "
|
||||
var ExcludeValue interface{}
|
||||
for i := 0; i < len1; i++ {
|
||||
field := t.Elem().Field(i)
|
||||
ufield := pp.Elem().FieldByName(field.Name)
|
||||
k := ufield.Kind()
|
||||
if field.Tag.Get("db") != Exclude && field.Tag.Get("db") != "id" {
|
||||
|
||||
if k == reflect.String {
|
||||
Values = append(Values, ufield.String())
|
||||
}
|
||||
if k == reflect.Int32 || k == reflect.Int || k == reflect.Int64 {
|
||||
Values = append(Values, ufield.Int())
|
||||
}
|
||||
Fields = append(Fields, "`"+field.Tag.Get("db")+"` = ?")
|
||||
}
|
||||
if field.Tag.Get("db") == Exclude {
|
||||
if k == reflect.String {
|
||||
ExcludeValue = ufield.String()
|
||||
}
|
||||
if k == reflect.Int32 || k == reflect.Int || k == reflect.Int64 {
|
||||
ExcludeValue = append(Values, ufield.Int())
|
||||
}
|
||||
}
|
||||
}
|
||||
Values = append(Values, ExcludeValue)
|
||||
origin += strings.Join(Fields, ",")
|
||||
origin = origin + " WHERE `" + Exclude + "` = ?"
|
||||
sqlStr := origin
|
||||
|
||||
_, err = SqlDb.Exec(sqlStr, Values...)
|
||||
if err != nil {
|
||||
log.Debug("update failed, sql %s err:%v\n", sqlStr, err)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func GetServerMailData(data *[]*SqlServerMailStruct) error {
|
||||
sql := "select * from system_mail_info"
|
||||
err := SqlDb.Select(data, sql)
|
||||
return err
|
||||
}
|
||||
|
||||
func CreateOrderSn(Uid, ChargeId int, OrderSn, Platform, Channel string, Price float64, Currency string) error {
|
||||
sql := "insert into t_player_charge (`Uid`,`OrderId`, `ProductId`, `Price`,`Currency`, `CreateTime`, `PayPlatform`, `PayChannel`) Values (?,?,?,?,?,?,?,?)"
|
||||
func GetActivityData(data *[]*SqlActivityCfgStruct) error {
|
||||
sql := "select `id`, `type`, `title`, `mail_title`, `mail_content`, `level_limit`, `start_time`, `end_time`, `cfg_buf`, `extra`, `interval` from t_activity_mod"
|
||||
err := SqlDb.Select(data, sql)
|
||||
return err
|
||||
}
|
||||
|
||||
func CreateOrderSn(Uid, ChargeId int, OrderSn, Platform, Channel string, Price float64, Currency, Extra string) error {
|
||||
sql := "insert into t_player_charge (`Uid`,`OrderId`, `ProductId`, `Price`,`Currency`, `CreateTime`, `PayPlatform`, `PayChannel`, `PayChannelExtra`) Values (?,?,?,?,?,?,?,?,?)"
|
||||
Now := GoUtil.Now()
|
||||
_, err := SqlDb.Exec(sql, Uid, OrderSn, ChargeId, Price, Currency, Now, Platform, Channel)
|
||||
_, err := SqlDb.Exec(sql, Uid, OrderSn, ChargeId, Price, Currency, Now, Platform, Channel, Extra)
|
||||
return err
|
||||
}
|
||||
|
||||
@ -444,8 +434,49 @@ func GetPlayerChargeData(OrderSn string) (*SqlChargeOrderStruct, error) {
|
||||
return data, err
|
||||
}
|
||||
|
||||
func GetPlayerChargeDataList(Uid int) ([]*SqlChargeOrderStruct, error) {
|
||||
sql := "select * from t_player_charge where Uid = ? and PayStatus = ?"
|
||||
data := &[]*SqlChargeOrderStruct{}
|
||||
err := SqlDb.Select(data, sql, Uid, MergeConst.ORDER_STATUS_PAY)
|
||||
return *data, err
|
||||
}
|
||||
|
||||
func GetPlayerPayChannelOrderId(OrderSn string) (*SqlChargeOrderStruct, error) {
|
||||
sql := "select * from t_player_charge where PayChannelOrderId = ?"
|
||||
data := &SqlChargeOrderStruct{}
|
||||
err := SqlDb.Get(data, sql, OrderSn)
|
||||
return data, err
|
||||
}
|
||||
|
||||
func UpdatePlayerChargeData(data *SqlChargeOrderStruct) error {
|
||||
sql := "update t_player_charge set PayTime = ?, PayStatus = ?, PayChannelOrderId = ? where OrderId = ?"
|
||||
_, err := SqlDb.Exec(sql, data.PayTime, data.PayStatus, data.PayChannelOrderId, data.OrderId)
|
||||
return err
|
||||
}
|
||||
|
||||
func SearchPlayer(key string) ([]*ResPlayerBaseInfo, error) {
|
||||
sql := "select * from t_player_baseinfo where nick_name like ? limit 10"
|
||||
data := &[]*ResPlayerBaseInfo{}
|
||||
err := SqlDb.Select(data, sql, "%"+key+"%")
|
||||
return *data, err
|
||||
}
|
||||
|
||||
func GetCommendPlayerFromDb(uid, login int64, level int) ([]int, error) {
|
||||
sqlStr := "SELECT dwUin FROM t_player_baseinfo WHERE dwUin != ? AND logout_time > ? AND level >= ? ORDER BY logout_time DESC LIMIT 1000"
|
||||
var res []int
|
||||
if err := SqlDb.Select(&res, sqlStr, uid, login, level); err != nil {
|
||||
log.Debug("table: %s, sql :%s, exec failed, err:%v\n", "PlayerBaseInfo", sqlStr, err)
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func GetDebugPlayer(uid int) ([]int, error) {
|
||||
sqlStr := "SELECT dwUin FROM t_player_baseinfo WHERE dwUin != ? ORDER BY login_time DESC LIMIT 1000"
|
||||
var res []int
|
||||
if err := SqlDb.Select(&res, sqlStr, uid); err != nil {
|
||||
log.Debug("table: %s, sql :%s, exec failed, err:%v\n", "PlayerBaseInfo", sqlStr, err)
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
@ -3,42 +3,128 @@ package db
|
||||
import (
|
||||
"context"
|
||||
"server/conf"
|
||||
"server/pkg/github.com/name5566/leaf/log"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"gitea.bywaystudios.com/pet_home/leaf/log"
|
||||
|
||||
"github.com/redis/go-redis/v9"
|
||||
)
|
||||
|
||||
var ctx = context.Background()
|
||||
|
||||
var Rdb *redis.Client
|
||||
var RdbWrite *redis.Client
|
||||
var RdbRead *redis.Client
|
||||
|
||||
func InitRedis() {
|
||||
rdb := redis.NewClient(&redis.Options{
|
||||
Addr: conf.Server.RedisAddr + ":" + conf.Server.RedisPort,
|
||||
Password: conf.Server.RedisPwd, // no password set
|
||||
DB: 0,
|
||||
})
|
||||
|
||||
_, err := rdb.Ping(ctx).Result()
|
||||
if err != nil {
|
||||
log.Debug("连接redis出错,错误信息:%v", err)
|
||||
return
|
||||
// helper: 创建单个客户端(addr 可以为 host:port 或 host)
|
||||
func connectClient(addr string) (*redis.Client, error) {
|
||||
if addr == "" {
|
||||
return nil, nil
|
||||
}
|
||||
log.Debug("成功连接redis")
|
||||
Rdb = rdb
|
||||
// 如果没有端口且配置了旧的 RedisPort,则尝试补端口
|
||||
if !strings.Contains(addr, ":") && conf.Server.RedisPort != "" {
|
||||
addr = addr + ":" + conf.Server.RedisPort
|
||||
}
|
||||
rdb := redis.NewClient(&redis.Options{
|
||||
Addr: addr,
|
||||
Password: conf.Server.RedisPwd,
|
||||
DB: conf.Server.RedisDb,
|
||||
})
|
||||
if _, err := rdb.Ping(ctx).Result(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return rdb, nil
|
||||
}
|
||||
|
||||
// InitRedis: 初始化读写分离客户端(向后兼容旧配置)
|
||||
func InitRedis() {
|
||||
// 决定写地址:优先使用 RedisWriteAddr,其次使用旧的 RedisAddr:RedisPort
|
||||
writeAddr := conf.Server.RedisWriteAddr
|
||||
if writeAddr == "" {
|
||||
if conf.Server.RedisAddr != "" {
|
||||
writeAddr = conf.Server.RedisAddr
|
||||
if conf.Server.RedisPort != "" && !strings.Contains(writeAddr, ":") {
|
||||
writeAddr = writeAddr + ":" + conf.Server.RedisPort
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 决定读地址:优先使用 RedisReadAddrs(逗号分隔),若为空则回退到写地址
|
||||
readAddrs := conf.Server.RedisReadAddrs
|
||||
if strings.TrimSpace(readAddrs) == "" {
|
||||
readAddrs = writeAddr
|
||||
}
|
||||
|
||||
// 取第一个可用的只读地址(简单实现)
|
||||
var readClient *redis.Client
|
||||
for _, a := range strings.Split(readAddrs, ",") {
|
||||
a = strings.TrimSpace(a)
|
||||
if a == "" {
|
||||
continue
|
||||
}
|
||||
c, err := connectClient(a)
|
||||
if err == nil {
|
||||
readClient = c
|
||||
break
|
||||
}
|
||||
log.Debug("connect read addr %s failed: %v", a, err)
|
||||
}
|
||||
|
||||
// 如果所有只读都不可用,尝试连接写地址作为回退
|
||||
writeClient, err := connectClient(writeAddr)
|
||||
if err != nil {
|
||||
log.Debug("连接redis写节点出错,错误信息:%v", err)
|
||||
// 若读已连上则也作为写回退,否则返回
|
||||
if readClient != nil {
|
||||
RdbWrite = readClient
|
||||
RdbRead = readClient
|
||||
log.Debug("只有只读节点可用,读写共用该节点")
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 如果读未连接成功,读回退到写
|
||||
if readClient == nil {
|
||||
readClient = writeClient
|
||||
}
|
||||
|
||||
RdbWrite = writeClient
|
||||
RdbRead = readClient
|
||||
log.Debug("成功初始化 redis(读写分离),写: %v, 读: %v", writeAddr, readAddrs)
|
||||
}
|
||||
|
||||
// 写操作使用 RdbWrite
|
||||
func RedisSetKey(key string, value string, expiration time.Duration) {
|
||||
err := Rdb.Set(ctx, key, value, expiration).Err()
|
||||
if RdbWrite == nil {
|
||||
log.Debug("redis write client is nil")
|
||||
return
|
||||
}
|
||||
err := RdbWrite.Set(ctx, key, value, expiration).Err()
|
||||
if err != nil {
|
||||
log.Debug("redis set failed, err:%v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
// 获取锁
|
||||
// 新增:写入字节数据,避免 string 转换拷贝
|
||||
func RedisSetKeyBytes(key string, value []byte, expiration time.Duration) {
|
||||
if RdbWrite == nil {
|
||||
log.Debug("redis write client is nil")
|
||||
return
|
||||
}
|
||||
err := RdbWrite.Set(ctx, key, value, expiration).Err()
|
||||
if err != nil {
|
||||
log.Debug("redis set failed, err:%v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
// 获取锁(写)
|
||||
func RedisLock(key string, value string, expiration time.Duration) bool {
|
||||
ok, err := Rdb.SetNX(ctx, key, value, expiration).Result()
|
||||
if RdbWrite == nil {
|
||||
log.Debug("redis write client is nil")
|
||||
return false
|
||||
}
|
||||
ok, err := RdbWrite.SetNX(ctx, key, value, expiration).Result()
|
||||
if err != nil {
|
||||
log.Debug("redis lock failed, err:%v\n", err)
|
||||
return false
|
||||
@ -46,8 +132,12 @@ func RedisLock(key string, value string, expiration time.Duration) bool {
|
||||
return ok
|
||||
}
|
||||
|
||||
// 释放锁
|
||||
// 释放锁(写)
|
||||
func RedisUnlock(key string, value string) bool {
|
||||
if RdbWrite == nil {
|
||||
log.Debug("redis write client is nil")
|
||||
return false
|
||||
}
|
||||
script := `
|
||||
if redis.call("GET", KEYS[1]) == ARGV[1] then
|
||||
return redis.call("DEL", KEYS[1])
|
||||
@ -55,7 +145,7 @@ func RedisUnlock(key string, value string) bool {
|
||||
return 0
|
||||
end
|
||||
`
|
||||
result, err := Rdb.Eval(ctx, script, []string{key}, value).Result()
|
||||
result, err := RdbWrite.Eval(ctx, script, []string{key}, value).Result()
|
||||
if err != nil {
|
||||
log.Debug("redis unlock failed, err:%v\n", err)
|
||||
return false
|
||||
@ -63,25 +153,134 @@ func RedisUnlock(key string, value string) bool {
|
||||
return result.(int64) == 1
|
||||
}
|
||||
|
||||
// 读操作使用 RdbRead
|
||||
func RedisGetKey(key string) (string, error) {
|
||||
val, err := Rdb.Get(ctx, key).Result()
|
||||
if RdbRead == nil {
|
||||
return "", nil
|
||||
}
|
||||
val, err := RdbRead.Get(ctx, key).Result()
|
||||
if err != nil {
|
||||
log.Debug("redis get failed, err:%v\n", err)
|
||||
return "", err
|
||||
}
|
||||
return val, nil
|
||||
}
|
||||
|
||||
func RedisGetKeyBytes(key string) ([]byte, error) {
|
||||
if RdbRead == nil {
|
||||
return nil, nil
|
||||
}
|
||||
val, err := RdbRead.Get(ctx, key).Bytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return val, nil
|
||||
}
|
||||
|
||||
func RedisDelKey(key string) {
|
||||
err := Rdb.Del(ctx, key).Err()
|
||||
if RdbWrite == nil {
|
||||
log.Debug("redis write client is nil")
|
||||
return
|
||||
}
|
||||
err := RdbWrite.Del(ctx, key).Err()
|
||||
if err != nil {
|
||||
log.Debug("redis del failed, err:%v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
func RedisZAdd(key string, member string, score float64) {
|
||||
err := Rdb.ZAdd(ctx, key, redis.Z{Score: score, Member: member}).Err()
|
||||
if RdbWrite == nil {
|
||||
log.Debug("redis write client is nil")
|
||||
return
|
||||
}
|
||||
err := RdbWrite.ZAdd(ctx, key, redis.Z{Score: score, Member: member}).Err()
|
||||
if err != nil {
|
||||
log.Debug("redis zadd failed, err:%v\n", err)
|
||||
return
|
||||
}
|
||||
const maxRankSize int64 = 10000
|
||||
count, err := RdbWrite.ZCard(ctx, key).Result()
|
||||
if err != nil {
|
||||
log.Debug("redis zcard failed, err:%v\n", err)
|
||||
return
|
||||
}
|
||||
if count > maxRankSize {
|
||||
removeCount := count - maxRankSize
|
||||
err = RdbWrite.ZRemRangeByRank(ctx, key, 0, removeCount-1).Err()
|
||||
if err != nil {
|
||||
log.Debug("redis zremrangebyrank failed, err:%v\n", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func RedisZRangeWithScores(key string, start, stop int64) ([]redis.Z, error) {
|
||||
if RdbRead == nil {
|
||||
return nil, nil
|
||||
}
|
||||
val, err := RdbRead.ZRangeWithScores(ctx, key, start, stop).Result()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return val, nil
|
||||
}
|
||||
|
||||
func RedisZRevRangeWithScores(key string, start, stop int64) ([]redis.Z, error) {
|
||||
if RdbRead == nil {
|
||||
return nil, nil
|
||||
}
|
||||
val, err := RdbRead.ZRevRangeWithScores(ctx, key, start, stop).Result()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return val, nil
|
||||
}
|
||||
|
||||
func RedisZGetByIndexWithScore(key string, index int64) (*redis.Z, error) {
|
||||
if RdbRead == nil {
|
||||
return nil, nil
|
||||
}
|
||||
val, err := RdbRead.ZRangeWithScores(ctx, key, index, index).Result()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(val) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
return &val[0], nil
|
||||
}
|
||||
|
||||
func RedisZRankWithScores(key, member string) (int64, float64, error) {
|
||||
if RdbRead == nil {
|
||||
return 0, 0, nil
|
||||
}
|
||||
val, err := RdbRead.ZRank(ctx, key, member).Result()
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
score, err := RdbRead.ZScore(ctx, key, member).Result()
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
return val, score, nil
|
||||
}
|
||||
|
||||
func RedisZCard(key string) (int64, error) {
|
||||
if RdbRead == nil {
|
||||
return 0, nil
|
||||
}
|
||||
val, err := RdbRead.ZCard(ctx, key).Result()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return val, nil
|
||||
}
|
||||
|
||||
func RedisDel(key string) {
|
||||
if RdbWrite == nil {
|
||||
log.Debug("redis write client is nil")
|
||||
return
|
||||
}
|
||||
err := RdbWrite.Del(ctx, key).Err()
|
||||
if err != nil {
|
||||
log.Debug("redis del failed, err:%v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,10 +20,12 @@ type Db_Account struct {
|
||||
Channel string `db:"channel"`
|
||||
DeviceId string `db:"device_id"`
|
||||
AutoId int `db:"auto_id"`
|
||||
IdName string `db:"id_name"`
|
||||
IdNum string `db:"id_num"`
|
||||
}
|
||||
|
||||
type ResPlayerBaseInfo struct {
|
||||
DwUin int32 `db:"dwUin"`
|
||||
DwUin int64 `db:"dwUin"`
|
||||
Energy int32 `db:"energy"`
|
||||
Star int32 `db:"star"`
|
||||
RecoverTime int32 `db:"recover_time"`
|
||||
@ -35,11 +37,12 @@ type ResPlayerBaseInfo struct {
|
||||
Guild int32 `db:"guild"`
|
||||
PackUnlockCount int32 `db:"pack_unlock_count"`
|
||||
LastPlayTime int32 `db:"last_play_time"`
|
||||
EnergyBuyCount int32 `db:"EnergyBuyCount"`
|
||||
Ban int64 `db:"ban"`
|
||||
UserName string `db:"user_name"`
|
||||
NickName string `db:"nick_name"`
|
||||
LoginTime int32 `db:"login_time"`
|
||||
LogoutTime int32 `db:"logout_time"`
|
||||
Todayolinetime int32 `db:"todayolinetime"`
|
||||
Node int32 `db:"node"`
|
||||
Rolecreatetime int32 `db:"rolecreatetime"`
|
||||
EmitOrderCnt int32 `db:"EmitOrderCnt"`
|
||||
DailyRenewTime int32 `db:"DailyRenewTime"`
|
||||
@ -458,7 +461,7 @@ type SqlAddFriendStruct struct {
|
||||
}
|
||||
|
||||
type SqlModStruct struct {
|
||||
DwUin int32 `db:"dwUin"`
|
||||
DwUin int64 `db:"dwUin"`
|
||||
ModData []byte `db:"mData"`
|
||||
UpdataTime int32 `db:"updateTime"`
|
||||
}
|
||||
@ -471,15 +474,41 @@ type SqlServerModStruct struct {
|
||||
}
|
||||
|
||||
type SqlServerMailStruct struct {
|
||||
Id int `db:"mail_id"`
|
||||
Title string `db:"title"`
|
||||
Content string `db:"content"`
|
||||
Items string `db:"items"`
|
||||
Start_time int64 `db:"start_time"`
|
||||
Register_time int64 `db:"register_time"`
|
||||
End_time int64 `db:"end_time"`
|
||||
Mail_type int `db:"mail_type"`
|
||||
To_uids string `db:"to_uids"`
|
||||
Id int `db:"mail_id"`
|
||||
Title string `db:"title"`
|
||||
Content string `db:"content"`
|
||||
SubTitle string `db:"subTitle"`
|
||||
SubTitleEn string `db:"subTitle_en"`
|
||||
TitleEn string `db:"title_en"`
|
||||
ContentEn string `db:"content_en"`
|
||||
TitlePtBr string `db:"title_ptbr"`
|
||||
SubTitlePtBr string `db:"subTitle_ptbr"`
|
||||
ContentPtBr string `db:"content_ptbr"`
|
||||
TitleEsLatam string `db:"title_es_latam"`
|
||||
SubTitleEsLatam string `db:"subTitle_es_latam"`
|
||||
ContentEsLatam string `db:"content_es_latam"`
|
||||
Items string `db:"items"`
|
||||
Start_time int64 `db:"start_time"`
|
||||
Register_time int64 `db:"register_time"`
|
||||
End_time int64 `db:"end_time"`
|
||||
Mail_type int `db:"mail_type"`
|
||||
Send_type int `db:"send_type"`
|
||||
To_uids string `db:"to_uids"`
|
||||
CreateTime int64 `db:"create_time"`
|
||||
}
|
||||
|
||||
type SqlActivityCfgStruct struct {
|
||||
Id int `db:"id"`
|
||||
Type int `db:"type"`
|
||||
Title string `db:"title"`
|
||||
MailTitle string `db:"mail_title"`
|
||||
MailContent string `db:"mail_content"`
|
||||
Level int `db:"level_limit"`
|
||||
Start_time int64 `db:"start_time"`
|
||||
End_time int64 `db:"end_time"`
|
||||
Cfg []byte `db:"cfg_buf"`
|
||||
Interval int64 `db:"interval"`
|
||||
Extra string `db:"extra"`
|
||||
}
|
||||
|
||||
type SqlChargeOrderStruct struct {
|
||||
|
||||
41
src/server/ga/log.go
Normal file
41
src/server/ga/log.go
Normal file
@ -0,0 +1,41 @@
|
||||
package ga
|
||||
|
||||
import (
|
||||
galog "gitea.bywaystudios.com/pet_home/galog"
|
||||
)
|
||||
|
||||
const (
|
||||
PROJECT_ID = "20659"
|
||||
CLIENT_ID = "Android_5.00_tyGuest,facebook.googleplay.0-hall20659.googleplay.Meowment"
|
||||
)
|
||||
|
||||
var glogger *galog.GALogger
|
||||
|
||||
func init() {
|
||||
glog, err := galog.NewGALogger("logs", PROJECT_ID, CLIENT_ID, galog.LogTypeTrack)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
glogger = glog
|
||||
}
|
||||
|
||||
func GAlogEvent(event string, userID string, deviceID string, properties map[string]interface{}) {
|
||||
newProperties := make(map[string]interface{})
|
||||
for k, v := range properties {
|
||||
// // JSON encode the value
|
||||
// jsonBytes, err := json.Marshal(v)
|
||||
// if err != nil {
|
||||
// newProperties["proj_"+k] = fmt.Sprintf("%v", v) // 无法解析直接转为字符串
|
||||
// continue
|
||||
// }
|
||||
// newProperties["proj_"+k] = string(jsonBytes)
|
||||
newProperties["proj_"+k] = v
|
||||
}
|
||||
properties = newProperties
|
||||
glogger.
|
||||
GetEntry(event).
|
||||
SetDeviceID(deviceID).
|
||||
SetUserID(userID).
|
||||
SetProperties(properties).
|
||||
Flush()
|
||||
}
|
||||
21
src/server/ga/te.go
Normal file
21
src/server/ga/te.go
Normal file
@ -0,0 +1,21 @@
|
||||
package ga
|
||||
|
||||
import (
|
||||
"server/conf"
|
||||
|
||||
thinkingdata "gitea.bywaystudios.com/pet_home/thinkdata"
|
||||
)
|
||||
|
||||
var Te thinkingdata.TDAnalytics
|
||||
|
||||
func init() {
|
||||
// 初始化
|
||||
// 创建 LogConfig 配置文件
|
||||
config := thinkingdata.TDLogConsumerConfig{
|
||||
Directory: conf.Server.TELOGDIR, // 事件采集的文件路径
|
||||
}
|
||||
// 初始化 logConsumer
|
||||
consumer, _ := thinkingdata.NewLogConsumerWithConfig(config)
|
||||
// 创建 te 对象
|
||||
Te = thinkingdata.New(consumer)
|
||||
}
|
||||
@ -1,785 +0,0 @@
|
||||
package game
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"math/rand"
|
||||
"server/GoUtil"
|
||||
"server/MergeConst"
|
||||
"server/db"
|
||||
"server/msg"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/robfig/cron/v3"
|
||||
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
type ChampshipsManager struct {
|
||||
MStatus int32
|
||||
MChampshipMap map[int32]*db.SqlChampshipsStruct
|
||||
MChampshipPlayerMap map[int32][]*msg.ChampshipsPlayerInfo
|
||||
IsSettle int32
|
||||
IsLoadDB bool
|
||||
MUpdateNotifyList []int32
|
||||
McronSave *cron.Cron
|
||||
McronSaveID cron.EntryID
|
||||
RobotCronID cron.EntryID
|
||||
RobotCronID10s cron.EntryID
|
||||
MPlayerBaseInfoMap map[int32]*db.ResPlayerBaseInfo
|
||||
}
|
||||
|
||||
func (p *ChampshipsManager) SaveDataFromDB(Key interface{}) bool {
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (p *ChampshipsManager) AIGrow1() {
|
||||
|
||||
}
|
||||
|
||||
func (p *ChampshipsManager) DeleteOutLineChampship(CurChampshipsId int32) {
|
||||
sqlStr := "DELETE FROM t_championships_data WHERE CurChampshipsId = ?"
|
||||
|
||||
for k, v := range p.MChampshipPlayerMap {
|
||||
if v[0].CurChampshipsId == CurChampshipsId {
|
||||
delete(p.MChampshipPlayerMap, k)
|
||||
}
|
||||
}
|
||||
result, err := db.SqlDb.Exec(sqlStr, CurChampshipsId)
|
||||
if err != nil {
|
||||
fmt.Printf("exec failed, err:%v\n", err)
|
||||
return
|
||||
}
|
||||
affectedRows, err := result.RowsAffected()
|
||||
if err != nil {
|
||||
fmt.Printf("get affected failed, err:%v\n", err)
|
||||
return
|
||||
} else {
|
||||
fmt.Printf("delete t_championships_data affectedRows:%d\n", affectedRows)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *ChampshipsManager) DeleteUneffectPlayer(deleteIds []int32) {
|
||||
sqlStr := "DELETE FROM t_player_baseinfo WHERE dwUin = ?"
|
||||
|
||||
for i := 0; i < len(deleteIds); i++ {
|
||||
_, err := db.SqlDb.Exec(sqlStr, deleteIds[i])
|
||||
if err != nil {
|
||||
fmt.Printf("exec failed, err:%v\n", err)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func (p *ChampshipsManager) GetFriendListId(id int32) []int32 {
|
||||
|
||||
sqlStr := "SELECT * FROM t_player_Friend_Data WHERE dwUin = ?"
|
||||
sqlStruck := db.SqlFriendStruct{}
|
||||
ret := []int32{}
|
||||
|
||||
if err := db.SqlDb.Get(&sqlStruck, sqlStr, id); err != nil {
|
||||
fmt.Printf("get data failed, err:%v\n", err)
|
||||
|
||||
} else {
|
||||
if sqlStruck.FriendList != "" {
|
||||
arr := strings.Split(sqlStruck.FriendList, "_")
|
||||
for i := 0; i < len(arr); i++ {
|
||||
id, _ := strconv.ParseInt(arr[i], 10, 32)
|
||||
ret = append(ret, int32(id))
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (p *ChampshipsManager) NotifyOpenNewChampShip(args []interface{}) {
|
||||
go func() {
|
||||
G_GameLogicPtr.M_SvrGlobal.CurChampshipsId = G_GameLogicPtr.M_SvrGlobal.CurChampshipsId + 1
|
||||
G_GameLogicPtr.M_SvrGlobal.StartChampshipsSvrTime = args[0].(int32)
|
||||
}()
|
||||
}
|
||||
|
||||
func (p *ChampshipsManager) OpenNewChampShip(args []interface{}) {
|
||||
|
||||
G_GameLogicPtr.M_SvrGlobal.CurChampshipsId = G_GameLogicPtr.M_SvrGlobal.CurChampshipsId + 1
|
||||
G_GameLogicPtr.M_SvrGlobal.StartChampshipsSvrTime = args[0].(int32)
|
||||
p.MUpdateNotifyList = []int32{}
|
||||
|
||||
sqlStr := "SELECT * FROM t_player_baseinfo"
|
||||
sqlStrucks := []db.ResPlayerBaseInfo{}
|
||||
if err := db.SqlDb.Select(&sqlStrucks, sqlStr); err != nil {
|
||||
fmt.Printf("get data failed, err:%v\n", err)
|
||||
return
|
||||
} else {
|
||||
|
||||
}
|
||||
deleteIds := []int32{}
|
||||
sqlStrucksList := []db.ResPlayerBaseInfo{}
|
||||
for i := 0; i < len(sqlStrucks); i++ {
|
||||
if sqlStrucks[i].UserName == "" {
|
||||
deleteIds = append(deleteIds, sqlStrucks[i].DwUin)
|
||||
} else {
|
||||
sqlStrucksList = append(sqlStrucksList, sqlStrucks[i])
|
||||
}
|
||||
}
|
||||
sqlStrucks = sqlStrucksList
|
||||
p.DeleteUneffectPlayer(deleteIds)
|
||||
|
||||
sort.Slice(sqlStrucks, func(i, j int) bool {
|
||||
if sqlStrucks[i].Level != sqlStrucks[j].Level {
|
||||
return sqlStrucks[i].Level < sqlStrucks[j].Level
|
||||
} else {
|
||||
return sqlStrucks[i].Exp < sqlStrucks[j].Exp
|
||||
}
|
||||
|
||||
})
|
||||
var playerCnt int = 15
|
||||
groups := int(math.Ceil((float64)(len(sqlStrucks)) / float64(playerCnt)))
|
||||
StartRobotUin := 200000
|
||||
p.MStatus = 1
|
||||
rand.Seed(time.Now().Unix())
|
||||
for i := 0; i < groups; i++ {
|
||||
if i < groups-1 {
|
||||
temp := db.SqlChampshipsStruct{}
|
||||
temp.CurChampshipsId = G_GameLogicPtr.M_SvrGlobal.CurChampshipsId
|
||||
CSPlayerInfo := []*msg.ChampshipsPlayerInfo{}
|
||||
|
||||
strr := []string{}
|
||||
for j := 0; j < int(playerCnt); j++ {
|
||||
dwUin := sqlStrucks[i*int(playerCnt)+j].DwUin
|
||||
res := strconv.Itoa(int(dwUin)) + "_" + "1" + "_" + "0" + "_" + "0" + "_" + "1" + "_" + strconv.Itoa(int(G_GameLogicPtr.M_SvrGlobal.CurChampshipsId)) + "_0"
|
||||
strr = append(strr, res)
|
||||
playerinfo := &msg.ChampshipsPlayerInfo{}
|
||||
playerinfo.DwUin = dwUin
|
||||
playerinfo.IsGet = 0
|
||||
playerinfo.IsPlayer = 1
|
||||
playerinfo.Score = 0
|
||||
playerinfo.Times = 1
|
||||
playerinfo.AIEnum = 0
|
||||
playerinfo.CurChampshipsId = G_GameLogicPtr.M_SvrGlobal.CurChampshipsId
|
||||
CSPlayerInfo = append(CSPlayerInfo, playerinfo)
|
||||
}
|
||||
for j := int(playerCnt); j < 30; j++ {
|
||||
StartRobotUin = StartRobotUin + 1
|
||||
dwUin := StartRobotUin
|
||||
enum := rand.Intn(4) + 1
|
||||
res := strconv.Itoa(int(dwUin)) + "_" + "0" + "_" + "0" + "_" + "0" + "_" + "1" + "_" + strconv.Itoa(int(G_GameLogicPtr.M_SvrGlobal.CurChampshipsId)) + "_" + strconv.Itoa(enum)
|
||||
strr = append(strr, res)
|
||||
playerinfo := &msg.ChampshipsPlayerInfo{}
|
||||
playerinfo.DwUin = int32(dwUin)
|
||||
playerinfo.IsGet = 0
|
||||
playerinfo.IsPlayer = 0
|
||||
playerinfo.Score = 0
|
||||
playerinfo.Times = 1
|
||||
playerinfo.AIEnum = int32(enum)
|
||||
playerinfo.CurChampshipsId = G_GameLogicPtr.M_SvrGlobal.CurChampshipsId
|
||||
CSPlayerInfo = append(CSPlayerInfo, playerinfo)
|
||||
}
|
||||
temp.GroupRankData = strings.Join(strr, ";")
|
||||
insertId, _ := db.FormatAllMemInsertDb(&temp, "t_championships_data")
|
||||
|
||||
p.MChampshipPlayerMap[int32(insertId)] = CSPlayerInfo
|
||||
|
||||
for j := 0; j < int(playerCnt); j++ {
|
||||
dwUin := sqlStrucks[i*int(playerCnt)+j].DwUin
|
||||
player, ok := G_GameLogicPtr.M_Players[dwUin]
|
||||
if ok {
|
||||
player.GetIFGameData("PlayerBaseData").(*PlayerBaseData).SetChampshipID(int32(insertId), true)
|
||||
} else {
|
||||
player = G_GameLogicPtr.FindOfflinePlayer(dwUin)
|
||||
if player != nil {
|
||||
player.GetIFGameData("PlayerBaseData").(*PlayerBaseData).SetChampshipID(int32(insertId), false)
|
||||
} else {
|
||||
sqlStrucks[i*int(playerCnt)+j].LastChampGroupID = sqlStrucks[i*int(playerCnt)+j].ChampshipsGroupID
|
||||
sqlStrucks[i*int(playerCnt)+j].ChampshipsGroupID = int32(insertId)
|
||||
db.FormatAllMemUpdateDb(&sqlStrucks[i*int(playerCnt)+j], "t_player_baseinfo", "dwUin")
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
remain := len(sqlStrucks) - (groups-1)*int(playerCnt)
|
||||
cnt := 0
|
||||
strr := []string{}
|
||||
temp := db.SqlChampshipsStruct{}
|
||||
temp.CurChampshipsId = G_GameLogicPtr.M_SvrGlobal.CurChampshipsId
|
||||
|
||||
CSPlayerInfo := []*msg.ChampshipsPlayerInfo{}
|
||||
|
||||
for j := 0; j < remain; j++ {
|
||||
dwUin := sqlStrucks[i*int(playerCnt)+j].DwUin
|
||||
res := strconv.Itoa(int(dwUin)) + "_" + "1" + "_" + "0" + "_" + "0" + "_" + "1" + "_" + strconv.Itoa(int(G_GameLogicPtr.M_SvrGlobal.CurChampshipsId)) + "_0"
|
||||
strr = append(strr, res)
|
||||
cnt = cnt + 1
|
||||
playerinfo := &msg.ChampshipsPlayerInfo{}
|
||||
playerinfo.DwUin = dwUin
|
||||
playerinfo.IsGet = 0
|
||||
playerinfo.IsPlayer = 1
|
||||
playerinfo.Score = 0
|
||||
playerinfo.Times = 1
|
||||
playerinfo.AIEnum = 0
|
||||
playerinfo.CurChampshipsId = G_GameLogicPtr.M_SvrGlobal.CurChampshipsId
|
||||
CSPlayerInfo = append(CSPlayerInfo, playerinfo)
|
||||
}
|
||||
for j := cnt; j < 30; j++ {
|
||||
StartRobotUin = StartRobotUin + 1
|
||||
dwUin := StartRobotUin
|
||||
enum := rand.Intn(4) + 1
|
||||
res := strconv.Itoa(int(dwUin)) + "_" + "0" + "_" + "0" + "_" + "0" + "_" + "1" + "_" + strconv.Itoa(int(G_GameLogicPtr.M_SvrGlobal.CurChampshipsId)) + "_" + strconv.Itoa(enum)
|
||||
strr = append(strr, res)
|
||||
playerinfo := &msg.ChampshipsPlayerInfo{}
|
||||
playerinfo.DwUin = int32(dwUin)
|
||||
playerinfo.IsGet = 0
|
||||
playerinfo.IsPlayer = 0
|
||||
playerinfo.Score = 0
|
||||
playerinfo.Times = 1
|
||||
playerinfo.AIEnum = int32(enum)
|
||||
playerinfo.CurChampshipsId = G_GameLogicPtr.M_SvrGlobal.CurChampshipsId
|
||||
CSPlayerInfo = append(CSPlayerInfo, playerinfo)
|
||||
}
|
||||
temp.GroupRankData = strings.Join(strr, ";")
|
||||
insertId, _ := db.FormatAllMemInsertDb(&temp, "t_championships_data")
|
||||
p.MChampshipPlayerMap[int32(insertId)] = CSPlayerInfo
|
||||
for j := 0; j < remain; j++ {
|
||||
dwUin := sqlStrucks[i*int(playerCnt)+j].DwUin
|
||||
player, ok := G_GameLogicPtr.M_Players[dwUin]
|
||||
if ok {
|
||||
player.GetIFGameData("PlayerBaseData").(*PlayerBaseData).SetChampshipID(int32(insertId), true)
|
||||
} else {
|
||||
player = G_GameLogicPtr.FindOfflinePlayer(dwUin)
|
||||
if player != nil {
|
||||
player.GetIFGameData("PlayerBaseData").(*PlayerBaseData).SetChampshipID(int32(insertId), false)
|
||||
} else {
|
||||
|
||||
sqlStrucks[i*int(playerCnt)+j].LastChampGroupID = sqlStrucks[i*int(playerCnt)+j].ChampshipsGroupID
|
||||
sqlStrucks[i*int(playerCnt)+j].ChampshipsGroupID = int32(insertId)
|
||||
db.FormatAllMemUpdateDb(&sqlStrucks[i*int(playerCnt)+j], "t_player_baseinfo", "dwUin")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
p.IsLoadDB = true
|
||||
|
||||
p.AIScoreGrowth1h()
|
||||
db.FormatAllMemUpdateDb(&G_GameLogicPtr.M_SvrGlobal, "t_server_global_data", "Id")
|
||||
|
||||
}
|
||||
|
||||
func (p *ChampshipsManager) OpenChampShipTimes(args []interface{}) {
|
||||
p.MStatus = 2
|
||||
notify := &msg.NotifyChampshipTimesOpen{}
|
||||
notify.CurChampshipsId = G_GameLogicPtr.M_SvrGlobal.CurChampshipsId
|
||||
data, _ := proto.Marshal(notify)
|
||||
G_GameLogicPtr.broadcastInfoAllPlayer("NotifyChampshipTimesOpen", data)
|
||||
}
|
||||
|
||||
func (p *ChampshipsManager) CloseChampShipTimes(args []interface{}) {
|
||||
p.MStatus = 1
|
||||
notify := &msg.NotifyChampshipTimesClose{}
|
||||
notify.CurChampshipsId = G_GameLogicPtr.M_SvrGlobal.CurChampshipsId
|
||||
data, _ := proto.Marshal(notify)
|
||||
G_GameLogicPtr.broadcastInfoAllPlayer("NotifyChampshipTimesClose", data)
|
||||
}
|
||||
|
||||
func (p *ChampshipsManager) Notify_Clock_Tick_Sec(args []interface{}) {
|
||||
timeStamp := args[0].(int64)
|
||||
t := time.Unix(timeStamp, 0).Local()
|
||||
zero := timeStamp - (int64)(t.Hour()*3600+t.Minute()*60+t.Second())
|
||||
OpenTime := zero + MergeConst.G_Champion_Start_Offset
|
||||
OpenTimesTime := zero + MergeConst.G_Champion_Start_Effect_Time
|
||||
CloseTimesTime := zero + MergeConst.G_Champion_Start_Effect_Time + MergeConst.G_Champion_Start_Effect_Durtion
|
||||
DeleteLastTimesTime := zero + MergeConst.G_Champion_settlement_Duration
|
||||
if G_GameLogicPtr.M_SvrGlobal.StartChampshipsSvrTime < int32(OpenTime) { //今日没有开启
|
||||
if timeStamp >= OpenTime { //开启
|
||||
GoUtil.CallEvent(MergeConst.Notify_Champion_Renew, []interface{}{int32(OpenTime)})
|
||||
} else {
|
||||
//开启时间未到
|
||||
if p.MStatus == 1 {
|
||||
GoUtil.CallEvent(MergeConst.Notify_EndChampShip, []interface{}{int32(OpenTime)})
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
if p.MStatus == 0 {
|
||||
p.MStatus = 1
|
||||
}
|
||||
|
||||
if !p.IsLoadDB {
|
||||
p.LoadDbDataByGroupId(G_GameLogicPtr.M_SvrGlobal.CurChampshipsId)
|
||||
if G_GameLogicPtr.M_SvrGlobal.LastChampshipsId > 0 {
|
||||
p.LoadDbDataByGroupId(G_GameLogicPtr.M_SvrGlobal.LastChampshipsId)
|
||||
}
|
||||
p.IsLoadDB = true
|
||||
}
|
||||
}
|
||||
|
||||
if p.MStatus == 1 {
|
||||
if timeStamp >= OpenTimesTime && timeStamp <= CloseTimesTime {
|
||||
GoUtil.CallEvent(MergeConst.Notify_OpenChampShipTimes, []interface{}{int32(OpenTime)})
|
||||
}
|
||||
|
||||
}
|
||||
if p.MStatus == 2 {
|
||||
if timeStamp > CloseTimesTime {
|
||||
GoUtil.CallEvent(MergeConst.Notify_CloseChampShipTimes, []interface{}{int32(OpenTime)})
|
||||
}
|
||||
}
|
||||
if p.IsSettle == 0 {
|
||||
if timeStamp <= DeleteLastTimesTime {
|
||||
p.IsSettle = 1
|
||||
} else {
|
||||
if G_GameLogicPtr.M_SvrGlobal.LastChampshipsId > 0 {
|
||||
p.DeleteOutLineChampship(G_GameLogicPtr.M_SvrGlobal.LastChampshipsId)
|
||||
G_GameLogicPtr.M_SvrGlobal.LastChampshipsId = 0
|
||||
db.FormatAllMemUpdateDb(&G_GameLogicPtr.M_SvrGlobal, "t_server_global_data", "Id")
|
||||
}
|
||||
}
|
||||
}
|
||||
if p.IsSettle == 1 {
|
||||
if timeStamp > DeleteLastTimesTime {
|
||||
notify := &msg.NotifyChampshipSettleClose{}
|
||||
notify.LastChampshipsId = G_GameLogicPtr.M_SvrGlobal.LastChampshipsId
|
||||
data, _ := proto.Marshal(notify)
|
||||
G_GameLogicPtr.broadcastInfoAllPlayer("NotifyChampshipSettleClose", data)
|
||||
p.IsSettle = 0
|
||||
if G_GameLogicPtr.M_SvrGlobal.LastChampshipsId > 0 {
|
||||
p.DeleteOutLineChampship(G_GameLogicPtr.M_SvrGlobal.LastChampshipsId)
|
||||
G_GameLogicPtr.M_SvrGlobal.LastChampshipsId = 0
|
||||
db.FormatAllMemUpdateDb(&G_GameLogicPtr.M_SvrGlobal, "t_server_global_data", "Id")
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *ChampshipsManager) EndChampShip(args []interface{}) {
|
||||
p.MStatus = 0
|
||||
G_GameLogicPtr.M_SvrGlobal.LastChampshipsId = G_GameLogicPtr.M_SvrGlobal.CurChampshipsId
|
||||
db.FormatAllMemUpdateDb(&G_GameLogicPtr.M_SvrGlobal, "t_server_global_data", "Id")
|
||||
|
||||
notify := &msg.NotifyChampshipSettleOpen{}
|
||||
notify.LastChampshipsId = G_GameLogicPtr.M_SvrGlobal.LastChampshipsId
|
||||
data, _ := proto.Marshal(notify)
|
||||
G_GameLogicPtr.broadcastInfoAllPlayer("NotifyChampshipSettleOpen", data)
|
||||
|
||||
notify1 := &msg.NotifyChampshipClose{}
|
||||
notify1.CurChampshipsId = G_GameLogicPtr.M_SvrGlobal.CurChampshipsId
|
||||
data1, _ := proto.Marshal(notify1)
|
||||
G_GameLogicPtr.broadcastInfoAllPlayer("NotifyChampshipClose", data1)
|
||||
|
||||
p.NotifyRenewChampshipData()
|
||||
}
|
||||
|
||||
func (p *ChampshipsManager) NotifyRenewChampshipData() {
|
||||
for i := 0; i < len(p.MUpdateNotifyList); i++ {
|
||||
groupid := p.MUpdateNotifyList[i]
|
||||
playerlist, ok := p.MChampshipPlayerMap[groupid]
|
||||
if ok {
|
||||
for j := 0; j < len(playerlist); j++ {
|
||||
if playerlist[j].IsPlayer == 1 {
|
||||
dwUin := playerlist[j].DwUin
|
||||
player, ok1 := G_GameLogicPtr.M_Players[dwUin]
|
||||
if ok1 {
|
||||
agent := player.GetAgentByPlayer()
|
||||
notify := &msg.NotifyUpdateChampshipRank{}
|
||||
notify.ChampshipsGroupID = groupid
|
||||
notify.GroupRankDataList = playerlist
|
||||
data, _ := proto.Marshal(notify)
|
||||
G_getGameLogic().PackResInfo(agent, "NotifyUpdateChampshipRank", data)
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
p.MUpdateNotifyList = p.MUpdateNotifyList[0:0]
|
||||
}
|
||||
|
||||
func (p *ChampshipsManager) ReqChampshipData(player *Player, buf []byte) {
|
||||
req := &msg.ReqChampshipData{}
|
||||
proto.Unmarshal(buf, req)
|
||||
res := &msg.ResChampshipData{}
|
||||
_, ok := p.MChampshipPlayerMap[req.ChampshipsGroupID]
|
||||
if ok {
|
||||
res.GroupRankDataList = p.MChampshipPlayerMap[req.ChampshipsGroupID]
|
||||
}
|
||||
res.ChampshipsGroupID = req.ChampshipsGroupID
|
||||
res.Status = p.MStatus
|
||||
res.IsSettle = p.IsSettle
|
||||
res.EndTime = G_GameLogicPtr.M_SvrGlobal.StartChampshipsSvrTime + MergeConst.G_Champion_Duration
|
||||
res.EndSettleTime = G_GameLogicPtr.M_SvrGlobal.StartChampshipsSvrTime - MergeConst.G_Champion_Start_Offset + MergeConst.G_Champion_Start_Effect_Time + MergeConst.G_Champion_Start_Effect_Durtion
|
||||
agent := player.GetAgentByPlayer()
|
||||
data, _ := proto.Marshal(res)
|
||||
G_getGameLogic().PackResInfo(agent, "ResChampshipData", data)
|
||||
}
|
||||
|
||||
func (p *ChampshipsManager) InitManager() {
|
||||
GoUtil.RegisterEvent(MergeConst.Notify_Champion_Renew, p.OpenNewChampShip, p)
|
||||
GoUtil.RegisterEvent(MergeConst.Notify_OpenChampShipTimes, p.OpenChampShipTimes, p)
|
||||
GoUtil.RegisterEvent(MergeConst.Notify_CloseChampShipTimes, p.CloseChampShipTimes, p)
|
||||
GoUtil.RegisterEvent(MergeConst.Notify_EndChampShip, p.EndChampShip, p)
|
||||
GoUtil.RegisterEvent(MergeConst.Notify_Clock_Tick_Sec, p.Notify_Clock_Tick_Sec, p)
|
||||
p.MChampshipMap = make(map[int32]*db.SqlChampshipsStruct)
|
||||
p.MChampshipPlayerMap = make(map[int32][]*msg.ChampshipsPlayerInfo)
|
||||
p.MStatus = 0
|
||||
p.IsSettle = 0
|
||||
p.IsLoadDB = false
|
||||
p.MUpdateNotifyList = []int32{}
|
||||
p.McronSave = cron.New()
|
||||
p.McronSaveID, _ = p.McronSave.AddFunc("@every 70s", func() {
|
||||
p.NotifyRenewChampshipData()
|
||||
})
|
||||
p.RobotCronID, _ = p.McronSave.AddFunc("@every 1h", func() {
|
||||
p.AIScoreGrowth1h()
|
||||
})
|
||||
|
||||
p.RobotCronID10s, _ = p.McronSave.AddFunc("@every 15m", func() {
|
||||
if p.MStatus == 2 {
|
||||
p.RobotIntervalAddScore15m()
|
||||
}
|
||||
})
|
||||
p.McronSave.Start()
|
||||
}
|
||||
|
||||
func (p *ChampshipsManager) RobotIntervalAddScore() {
|
||||
seed := time.Now().Unix()
|
||||
rand.Seed(seed)
|
||||
needToUpdateDb := []int32{}
|
||||
for k, v := range p.MChampshipPlayerMap {
|
||||
ishaveRobot := false
|
||||
for i := 0; i < len(v); i++ {
|
||||
if v[i].IsPlayer == 0 {
|
||||
ishaveRobot = true
|
||||
addScore := 3
|
||||
ran := rand.Intn(100) + 1
|
||||
if ran <= 25 {
|
||||
addScore = addScore + 1
|
||||
} else {
|
||||
if ran <= 50 {
|
||||
addScore = addScore + 2
|
||||
}
|
||||
}
|
||||
v[i].Score = v[i].Score + int32(addScore)
|
||||
}
|
||||
}
|
||||
if ishaveRobot {
|
||||
sort.Slice(v, func(i, j int) bool { return v[i].Score > v[j].Score })
|
||||
isAdd := false
|
||||
for i := 0; i < len(p.MUpdateNotifyList); i++ {
|
||||
if p.MUpdateNotifyList[i] == k {
|
||||
isAdd = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !isAdd {
|
||||
p.MUpdateNotifyList = append(p.MUpdateNotifyList, k)
|
||||
}
|
||||
needToUpdateDb = append(needToUpdateDb, k)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
for i := 0; i < len(needToUpdateDb); i++ {
|
||||
p.SaveDbDataByGroupId(needToUpdateDb[i])
|
||||
}
|
||||
}
|
||||
|
||||
func (p *ChampshipsManager) GetMinGroupId() int32 {
|
||||
var Min int32 = 0
|
||||
for k := range p.MChampshipPlayerMap {
|
||||
if Min == 0 {
|
||||
Min = k
|
||||
continue
|
||||
}
|
||||
if k < Min {
|
||||
Min = k
|
||||
}
|
||||
}
|
||||
return Min
|
||||
}
|
||||
|
||||
func (p *ChampshipsManager) AIScoreGrowth1h() {
|
||||
seed := time.Now().Unix()
|
||||
rand.Seed(seed)
|
||||
needToUpdateDb := []int32{}
|
||||
// MinGroupId := p.GetMinGroupId()
|
||||
for k, v := range p.MChampshipPlayerMap {
|
||||
ishaveRobot := false
|
||||
groupId := 0 //k - MinGroupId + 1
|
||||
for i := 0; i < len(v); i++ {
|
||||
if v[i].IsPlayer == 0 {
|
||||
ishaveRobot = true
|
||||
addScore := 0
|
||||
if v[i].AIEnum == 1 {
|
||||
var num1 float64 = 0.5
|
||||
var num2 float64 = 5.5
|
||||
groupId = rand.Intn(7) + 1
|
||||
addScore = addScore + int(math.Floor(float64(groupId-1)*num1*num2))
|
||||
}
|
||||
if v[i].AIEnum == 2 {
|
||||
addScore = 16
|
||||
|
||||
ran := rand.Intn(100) + 1
|
||||
if ran <= 25 {
|
||||
addScore = addScore + 6
|
||||
} else {
|
||||
if ran <= 50 {
|
||||
addScore = addScore + 10
|
||||
}
|
||||
}
|
||||
}
|
||||
if v[i].AIEnum == 3 {
|
||||
addScore = 16
|
||||
|
||||
ran := rand.Intn(100) + 1
|
||||
if ran <= 25 {
|
||||
addScore = addScore + 10
|
||||
} else {
|
||||
if ran <= 75 {
|
||||
addScore = addScore + 6
|
||||
}
|
||||
}
|
||||
var num1 float64 = 0.5
|
||||
var num2 float64 = 5.5
|
||||
groupId = rand.Intn(7) + 1
|
||||
addScore = addScore + int(math.Floor(float64(groupId-1)*num1*num2))
|
||||
}
|
||||
if v[i].AIEnum == 4 {
|
||||
var num1 float64 = 0.5
|
||||
var num2 float64 = 5.5
|
||||
groupId = rand.Intn(7) + 1
|
||||
addScore = addScore + int(math.Floor(float64(groupId-1)*num1*num2))
|
||||
score := rand.Intn(23)
|
||||
addScore = addScore + score
|
||||
}
|
||||
v[i].Score = v[i].Score + int32(addScore)
|
||||
}
|
||||
}
|
||||
if ishaveRobot {
|
||||
sort.Slice(v, func(i, j int) bool { return v[i].Score > v[j].Score })
|
||||
isAdd := false
|
||||
for i := 0; i < len(p.MUpdateNotifyList); i++ {
|
||||
if p.MUpdateNotifyList[i] == k {
|
||||
isAdd = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !isAdd {
|
||||
p.MUpdateNotifyList = append(p.MUpdateNotifyList, k)
|
||||
}
|
||||
needToUpdateDb = append(needToUpdateDb, k)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
for i := 0; i < len(needToUpdateDb); i++ {
|
||||
p.SaveDbDataByGroupId(needToUpdateDb[i])
|
||||
}
|
||||
}
|
||||
|
||||
func (p *ChampshipsManager) RobotIntervalAddScore15m() {
|
||||
seed := time.Now().Unix()
|
||||
rand.Seed(seed)
|
||||
needToUpdateDb := []int32{}
|
||||
for k, v := range p.MChampshipPlayerMap {
|
||||
ishaveRobot := false
|
||||
for i := 0; i < len(v); i++ {
|
||||
if v[i].IsPlayer == 0 {
|
||||
|
||||
addScore := 0
|
||||
if v[i].AIEnum == 1 {
|
||||
|
||||
ran := rand.Intn(100) + 1
|
||||
if ran <= 25 {
|
||||
addScore = addScore + 10
|
||||
} else {
|
||||
if ran <= 75 {
|
||||
addScore = addScore + 6
|
||||
}
|
||||
}
|
||||
ran = rand.Intn(100) + 1
|
||||
if ran <= 25 {
|
||||
addScore = addScore + 5
|
||||
} else {
|
||||
if ran <= 50 {
|
||||
addScore = addScore + 10
|
||||
}
|
||||
}
|
||||
if addScore > 0 {
|
||||
ishaveRobot = true
|
||||
v[i].Score = v[i].Score + int32(addScore)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if ishaveRobot {
|
||||
sort.Slice(v, func(i, j int) bool { return v[i].Score > v[j].Score })
|
||||
isAdd := false
|
||||
for i := 0; i < len(p.MUpdateNotifyList); i++ {
|
||||
if p.MUpdateNotifyList[i] == k {
|
||||
isAdd = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !isAdd {
|
||||
p.MUpdateNotifyList = append(p.MUpdateNotifyList, k)
|
||||
}
|
||||
needToUpdateDb = append(needToUpdateDb, k)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
for i := 0; i < len(needToUpdateDb); i++ {
|
||||
p.SaveDbDataByGroupId(needToUpdateDb[i])
|
||||
}
|
||||
}
|
||||
func (p *ChampshipsManager) SaveDbDataByGroupId(GroupId int32) {
|
||||
_, ok := p.MChampshipPlayerMap[GroupId]
|
||||
if ok {
|
||||
List := p.MChampshipPlayerMap[GroupId]
|
||||
strr := []string{}
|
||||
for i := 0; i < len(List); i++ {
|
||||
Item := List[i]
|
||||
unit := strconv.Itoa(int(Item.DwUin)) + "_" + strconv.Itoa(int(Item.IsPlayer)) + "_" + strconv.Itoa(int(Item.Score)) + "_" + strconv.Itoa(int(Item.IsGet)) + "_" + strconv.Itoa(int(Item.Times)) + "_" + strconv.Itoa(int(Item.CurChampshipsId)) + "_" + strconv.Itoa(int(Item.AIEnum))
|
||||
strr = append(strr, unit)
|
||||
}
|
||||
data := strings.Join(strr, ";")
|
||||
sqlStruct := &db.SqlChampionshipsStruct{}
|
||||
sqlStruct.ChampshipsGroupID = GroupId
|
||||
sqlStruct.GroupRankData = data
|
||||
sqlStruct.CurChampshipsId = List[0].CurChampshipsId
|
||||
db.FormatAllMemUpdateDb(sqlStruct, "t_championships_data", "ChampshipsGroupID")
|
||||
}
|
||||
}
|
||||
|
||||
func (p *ChampshipsManager) LoadDbDataByGroupId(ChampshipsId int32) {
|
||||
|
||||
sqlStr := "SELECT * FROM t_championships_data WHERE CurChampshipsId = ?"
|
||||
|
||||
sqlStruck := []db.SqlChampionshipsStruct{}
|
||||
|
||||
if err := db.SqlDb.Select(&sqlStruck, sqlStr, ChampshipsId); err != nil {
|
||||
fmt.Printf("get data failed, err:%v\n", err)
|
||||
|
||||
} else {
|
||||
for m := 0; m < len(sqlStruck); m++ {
|
||||
units := strings.Split(sqlStruck[m].GroupRankData, ";")
|
||||
list := []*msg.ChampshipsPlayerInfo{}
|
||||
for i := 0; i < len(units); i++ {
|
||||
item := units[i]
|
||||
strr := strings.Split(item, "_")
|
||||
temp := &msg.ChampshipsPlayerInfo{}
|
||||
dwuin, _ := strconv.Atoi(strr[0])
|
||||
temp.DwUin = int32(dwuin)
|
||||
IsPlayer, _ := strconv.Atoi(strr[1])
|
||||
temp.IsPlayer = int32(IsPlayer)
|
||||
Score, _ := strconv.Atoi(strr[2])
|
||||
temp.Score = int32(Score)
|
||||
IsGet, _ := strconv.Atoi(strr[3])
|
||||
temp.IsGet = int32(IsGet)
|
||||
Times, _ := strconv.Atoi(strr[4])
|
||||
temp.Times = int32(Times)
|
||||
CS, _ := strconv.Atoi(strr[5])
|
||||
temp.CurChampshipsId = int32(CS)
|
||||
AI, _ := strconv.Atoi(strr[6])
|
||||
temp.AIEnum = int32(AI)
|
||||
list = append(list, temp)
|
||||
}
|
||||
p.MChampshipPlayerMap[sqlStruck[m].ChampshipsGroupID] = list
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (p *ChampshipsManager) ReqChampshipAddScore(player *Player, buf []byte) {
|
||||
req := &msg.ReqChampshipAddScore{}
|
||||
proto.Unmarshal(buf, req)
|
||||
res := &msg.ResChampshipAddScore{}
|
||||
|
||||
if p.MStatus == 0 {
|
||||
res.ResultCode = MergeConst.Protocol_Champship_End
|
||||
} else {
|
||||
_, ok := p.MChampshipPlayerMap[req.GroupId]
|
||||
if ok {
|
||||
List := p.MChampshipPlayerMap[req.GroupId]
|
||||
isHave := false
|
||||
for i := 0; i < len(List); i++ {
|
||||
if List[i].DwUin == player.M_DwUin {
|
||||
List[i].Score = List[i].Score + req.AddScore
|
||||
res.ResultCode = 0
|
||||
isHave = true
|
||||
break
|
||||
}
|
||||
}
|
||||
sort.Slice(List, func(i, j int) bool { return List[i].Score > List[j].Score })
|
||||
if !isHave {
|
||||
res.ResultCode = MergeConst.Protocol_Champship_No_Join
|
||||
} else {
|
||||
res.GroupRankDataList = List
|
||||
isAdd := false
|
||||
for i := 0; i < len(p.MUpdateNotifyList); i++ {
|
||||
if p.MUpdateNotifyList[i] == req.GroupId {
|
||||
isAdd = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !isAdd {
|
||||
p.MUpdateNotifyList = append(p.MUpdateNotifyList, req.GroupId)
|
||||
}
|
||||
|
||||
p.SaveDbDataByGroupId(req.GroupId)
|
||||
}
|
||||
} else {
|
||||
res.ResultCode = MergeConst.Protocol_Champship_No_Exsit
|
||||
}
|
||||
}
|
||||
|
||||
res.GroupId = req.GroupId
|
||||
agent := player.GetAgentByPlayer()
|
||||
data, _ := proto.Marshal(res)
|
||||
G_getGameLogic().PackResInfo(agent, "ResChampshipAddScore", data)
|
||||
}
|
||||
|
||||
func (p *ChampshipsManager) ReqChampshipAddTime(player *Player, buf []byte) {
|
||||
req := &msg.ReqChampshipAddTime{}
|
||||
proto.Unmarshal(buf, req)
|
||||
res := &msg.ResChampshipAddTime{}
|
||||
if p.MStatus == 0 {
|
||||
res.ResultCode = MergeConst.Protocol_Champship_End
|
||||
} else {
|
||||
_, ok := p.MChampshipPlayerMap[req.GroupId]
|
||||
if ok {
|
||||
List := p.MChampshipPlayerMap[req.GroupId]
|
||||
isHave := false
|
||||
for i := 0; i < len(List); i++ {
|
||||
if List[i].DwUin == player.M_DwUin {
|
||||
List[i].Times = List[i].Times + req.AddTimes
|
||||
res.ResultCode = 0
|
||||
isHave = true
|
||||
break
|
||||
}
|
||||
}
|
||||
sort.Slice(List, func(i, j int) bool { return List[i].Score > List[j].Score })
|
||||
if !isHave {
|
||||
res.ResultCode = MergeConst.Protocol_Champship_No_Join
|
||||
} else {
|
||||
res.GroupRankDataList = List
|
||||
p.SaveDbDataByGroupId(req.GroupId)
|
||||
}
|
||||
} else {
|
||||
res.ResultCode = MergeConst.Protocol_Champship_No_Exsit
|
||||
}
|
||||
}
|
||||
res.GroupId = req.GroupId
|
||||
|
||||
agent := player.GetAgentByPlayer()
|
||||
data, _ := proto.Marshal(res)
|
||||
G_getGameLogic().PackResInfo(agent, "ResChampshipAddTime", data)
|
||||
}
|
||||
@ -1,48 +0,0 @@
|
||||
package game
|
||||
|
||||
import "server/pkg/github.com/name5566/leaf/log"
|
||||
|
||||
func Charge(p *Player, ChargeId int) {
|
||||
ChargeFire(p, ChargeId) // 充值
|
||||
EndlessFire(p, ChargeId) // 无尽礼包
|
||||
PiggyBankFire(p, ChargeId) // 猪猪银行
|
||||
}
|
||||
|
||||
func PiggyBankFire(p *Player, ChargeId int) {
|
||||
PiggyBankMod := p.PlayMod.getPiggyBankMod()
|
||||
Item := PiggyBankMod.Fire(ChargeId)
|
||||
err := p.HandleItem(Item, "PiggyBank")
|
||||
if err != nil {
|
||||
log.Debug("ChargeFire err : %s", err)
|
||||
}
|
||||
LimitedTimePiggyBankTrigger(p)
|
||||
p.PlayMod.save()
|
||||
p.PushClientRes(PiggyBankMod.BackData())
|
||||
}
|
||||
|
||||
// 处理玩家充值
|
||||
func ChargeFire(p *Player, ChargeId int) {
|
||||
ChargeMod := p.PlayMod.getChargeMod()
|
||||
Item := ChargeMod.Fire(ChargeId)
|
||||
err := p.HandleItem(Item, "Charge")
|
||||
if err != nil {
|
||||
log.Debug("ChargeFire err : %s", err)
|
||||
}
|
||||
p.PlayMod.save()
|
||||
p.PushClientRes(ChargeMod.BackData())
|
||||
}
|
||||
|
||||
// 处理玩家充值
|
||||
func EndlessFire(p *Player, ChargeId int) {
|
||||
EndlessMod := p.PlayMod.getEndlessMod()
|
||||
Item := EndlessMod.Fire(ChargeId)
|
||||
if Item == nil {
|
||||
return
|
||||
}
|
||||
err := p.HandleItem(Item, "Endless")
|
||||
if err != nil {
|
||||
log.Debug("ChargeFire err : %s", err)
|
||||
}
|
||||
p.PlayMod.save()
|
||||
p.PushClientRes(EndlessMod.BackData())
|
||||
}
|
||||
@ -1,115 +0,0 @@
|
||||
package game
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"server/GoUtil"
|
||||
mergeCluster "server/cluster"
|
||||
"server/conf"
|
||||
"server/game/mod/msg"
|
||||
"server/pkg/github.com/name5566/leaf/log"
|
||||
)
|
||||
|
||||
type FriendMgr struct {
|
||||
*ServerMod
|
||||
}
|
||||
|
||||
type FirendData struct {
|
||||
List map[int][]*msg.Msg
|
||||
ClusterMsg map[int][]*msg.Msg
|
||||
}
|
||||
|
||||
func (f *FriendMgr) Init() {
|
||||
|
||||
f.key = FRIEND_MGR_KEY
|
||||
f.data = &FirendData{
|
||||
List: make(map[int][]*msg.Msg),
|
||||
ClusterMsg: make(map[int][]*msg.Msg),
|
||||
}
|
||||
// 注册处理函数
|
||||
f.init()
|
||||
f.RegisterHandler(msg.HANDLE_TYPE_APPLY, f.sendToPlayer)
|
||||
f.RegisterHandler(msg.HADNLE_TYPE_AGREE, f.sendToPlayer)
|
||||
f.RegisterHandler(msg.HANDLE_TYPE_DEL, f.sendToPlayer)
|
||||
f.RegisterHandler(msg.HANDLE_TYPE_SYNC, f.sync)
|
||||
|
||||
// 卡牌消息
|
||||
f.RegisterHandler(msg.HANDLE_TYPE_REQ_CARD, f.sendToPlayer)
|
||||
f.RegisterHandler(msg.HANDLE_TYPE_AGREE_CARD, f.sendToPlayer)
|
||||
f.RegisterHandler(msg.HANDLE_TYPE_REG_CARD_REFUSE, f.sendToPlayer)
|
||||
f.RegisterHandler(msg.HANDLE_TYPE_REG_CARD_FINISH, f.sendToPlayer)
|
||||
f.RegisterHandler(msg.HANDLE_TYPE_AGREE_CARD_FAIL, f.sendToPlayer)
|
||||
f.RegisterHandler(msg.HANDLE_TYPE_EX_CARD, f.sendToPlayer)
|
||||
f.RegisterHandler(msg.HANDLE_TYPE_SELECT_EX_CARD, f.sendToPlayer)
|
||||
f.RegisterHandler(msg.HANDLE_TYPE_ARGREE_EX_CARD, f.sendToPlayer)
|
||||
f.RegisterHandler(msg.HANDLE_TYPE_REFUSE_SELECT_CARD, f.sendToPlayer)
|
||||
f.RegisterHandler(msg.HANDLE_TYPE_REFUSE_EX_CARD, f.sendToPlayer)
|
||||
|
||||
}
|
||||
|
||||
func (f *FriendMgr) getData() *FirendData {
|
||||
return f.data.(*FirendData)
|
||||
}
|
||||
|
||||
// 通知玩家
|
||||
func (f *FriendMgr) sendToPlayer(m *msg.Msg) (interface{}, error) {
|
||||
err := sendToPlayer(m)
|
||||
if err != nil {
|
||||
log.Debug("send to player error : %s\n", err)
|
||||
ToServerId := GoUtil.GetServerIdByUid(m.To)
|
||||
if ToServerId != conf.Server.ServerID {
|
||||
f.getData().ClusterMsg[m.To] = append(f.getData().ClusterMsg[m.To], m) // 保存到集群消息
|
||||
} else {
|
||||
f.getData().List[m.To] = append(f.getData().List[m.To], m) // 保存到本地消息
|
||||
}
|
||||
f.update = true
|
||||
return nil, err
|
||||
}
|
||||
log.Debug("send to player success")
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// 同步信息
|
||||
func (f *FriendMgr) sync(m *msg.Msg) (interface{}, error) {
|
||||
data := f.getData().List[m.From]
|
||||
f.getData().List[m.From] = make([]*msg.Msg, 0)
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// 发送消息给玩家
|
||||
func sendToPlayer(m *msg.Msg) error {
|
||||
p := G_GameLogicPtr.GetPlayerByUid(m.To)
|
||||
if p == nil || p.stop {
|
||||
return fmt.Errorf("player %d not online", m.To)
|
||||
}
|
||||
p.SendMsg(m)
|
||||
return nil
|
||||
}
|
||||
|
||||
func FriendMgrSend(m *msg.Msg) error {
|
||||
ToServer := GoUtil.GetServerIdByUid(m.To)
|
||||
if ToServer != conf.Server.ServerID {
|
||||
err := mergeCluster.SendServerMsg(m, ToServer)
|
||||
if err != nil { // 区服不在线
|
||||
G_GameLogicPtr.FriendMgrSend(m)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
G_GameLogicPtr.FriendMgrSend(m)
|
||||
return nil
|
||||
}
|
||||
|
||||
// 集群好友消息同步
|
||||
func ClusterFriendSync(m *msg.Msg) error {
|
||||
log.Debug("ClusterFriendSync")
|
||||
if v, ok := G_GameLogicPtr.FriendMgr.getData().ClusterMsg[m.To]; ok {
|
||||
for _, msg := range v {
|
||||
mergeCluster.SendServerMsg(msg, m.To)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func FriendMgrCall(m *msg.Msg) interface{} {
|
||||
return G_GameLogicPtr.FriendMgrCall(m)
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,66 +0,0 @@
|
||||
package game
|
||||
|
||||
import (
|
||||
"server/game/mod/card"
|
||||
"server/game/mod/item"
|
||||
"server/msg"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
func ReqGmCommand(args []interface{}) error {
|
||||
_, player, buf := ParseArgs(args)
|
||||
detail := &msg.ReqGmCommand{}
|
||||
proto.Unmarshal(buf, detail)
|
||||
arg := strings.Split(detail.Command, " ")
|
||||
switch arg[0] {
|
||||
case "additem":
|
||||
id, _ := strconv.Atoi(arg[1])
|
||||
num, _ := strconv.Atoi(arg[2])
|
||||
player.HandleItem([]*item.Item{item.NewItem(id, num)}, "GM")
|
||||
case "subitem":
|
||||
id, _ := strconv.Atoi(arg[1])
|
||||
num, _ := strconv.Atoi(arg[2])
|
||||
player.HandleItem([]*item.Item{item.NewItem(id, -num)}, "GM")
|
||||
case "reset_order":
|
||||
player.PlayMod.mod_list.Order.Step = 0
|
||||
player.PlayMod.mod_list.Order.InitData()
|
||||
player.PushClientRes(player.PlayMod.mod_list.Order.BackData())
|
||||
case "add_card_star":
|
||||
num, _ := strconv.Atoi(arg[1])
|
||||
player.PlayMod.mod_list.Card.ExchangeStar += num
|
||||
player.PushClientRes(player.PlayMod.mod_list.Card.BackData())
|
||||
case "addexp":
|
||||
num, _ := strconv.Atoi(arg[1])
|
||||
player.GetPlayerBaseMod().AddExp(num)
|
||||
player.PushClientRes(&player.GetPlayerBaseMod().Data)
|
||||
case "setlv":
|
||||
num, _ := strconv.Atoi(arg[1])
|
||||
player.GetPlayerBaseMod().Data.Level = int32(num)
|
||||
player.GetPlayerBaseMod().Data.Exp = 0
|
||||
player.PushClientRes(&player.GetPlayerBaseMod().Data)
|
||||
case "zeroUpdate":
|
||||
player.PlayMod.getVarMod().DailyResetTime = 0
|
||||
player.ZeroUpdate([]interface{}{})
|
||||
case "setSevenLoginActive":
|
||||
num, _ := strconv.Atoi(arg[1])
|
||||
player.PlayMod.getSevenLoginMod().Active = num
|
||||
case "pay":
|
||||
ChargeId, _ := strconv.Atoi(arg[1])
|
||||
Charge(player, ChargeId)
|
||||
case "resetCardReq":
|
||||
CardMod := player.PlayMod.getCardMod()
|
||||
CardMod.ReqFriend = make(map[int]*card.CardInfo)
|
||||
CardMod.ExCard = make(map[int]*card.CardInfo)
|
||||
CardMod.ExTimes = 10
|
||||
CardMod.ReqTimes = 10
|
||||
|
||||
FriendMod := player.PlayMod.getFriendMod()
|
||||
FriendMod.ApplyCard = make(map[int]*card.CardInfo)
|
||||
FriendMod.ExchangeCard = make(map[int]*card.CardInfo)
|
||||
FriendMod.SelectCard = make(map[int]*card.CardInfo)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -1,79 +0,0 @@
|
||||
package game
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"server/conf"
|
||||
"server/msg"
|
||||
|
||||
// "server/msg"
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
type HttpManager struct {
|
||||
Rounter *mux.Router
|
||||
}
|
||||
|
||||
func (p *HttpManager) InitRounter() {
|
||||
p.Rounter = mux.NewRouter()
|
||||
p.InitFriendRouter()
|
||||
p.InitPlayerProfileInfo()
|
||||
http.ListenAndServe(conf.Server.HttpPort, p.Rounter)
|
||||
}
|
||||
|
||||
func (p *HttpManager) InitFriendRouter() {
|
||||
bs := p.Rounter.PathPrefix("/Friend").Subrouter()
|
||||
bs.HandleFunc("/Add/{SenderId}/{ReceiveId}", p.AddFriend)
|
||||
bs.HandleFunc("/Del/{SenderId}/{ReceiveId}", p.DeleteFriend)
|
||||
}
|
||||
|
||||
func (p *HttpManager) InitPlayerProfileInfo() {
|
||||
bs := p.Rounter.PathPrefix("/Profile").Subrouter()
|
||||
bs.HandleFunc("/GetBrief/{Id}", p.GetPlayerProfileInfo)
|
||||
}
|
||||
|
||||
func (p *HttpManager) GetPlayerProfileInfo(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
|
||||
Id, ok := vars["Id"]
|
||||
|
||||
if ok {
|
||||
Uin, _ := strconv.Atoi(Id)
|
||||
data := G_GameLogicPtr.MPlayerProfileManager.HttpReqPlayerBriefProfileData(int32(Uin))
|
||||
test := []*msg.ResPlayerBriefProfileData{data, data}
|
||||
bytes, _ := json.Marshal(test)
|
||||
|
||||
v := []*msg.ResPlayerBriefProfileData{}
|
||||
json.Unmarshal(bytes, &v)
|
||||
|
||||
fmt.Println("bytes Length:" + strconv.Itoa(len(v)))
|
||||
fmt.Println("bytes Length:" + strconv.Itoa(len(v)))
|
||||
w.Write(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *HttpManager) AddFriend(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
SenderId, ok := vars["SenderId"]
|
||||
if ok {
|
||||
fmt.Println("AddFreind SenderId:" + SenderId)
|
||||
}
|
||||
|
||||
ReceiveId, ok1 := vars["ReceiveId"]
|
||||
if ok1 {
|
||||
fmt.Println("AddFreind ReceiveId:" + ReceiveId)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *HttpManager) DeleteFriend(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
id, ok := vars["id"]
|
||||
if !ok {
|
||||
fmt.Println("id is missing in parameters")
|
||||
}
|
||||
fmt.Println(`id := `, id)
|
||||
|
||||
}
|
||||
@ -1,242 +0,0 @@
|
||||
package game
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/robfig/cron/v3"
|
||||
"server/GoUtil"
|
||||
"server/MergeConst"
|
||||
"server/db"
|
||||
"server/gamedata"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"server/pkg/github.com/name5566/leaf/timer"
|
||||
)
|
||||
|
||||
type LimitEventPeriod struct {
|
||||
StartCronID cron.EntryID
|
||||
EndTimer *timer.Timer
|
||||
StartTime int32
|
||||
EndTime int32
|
||||
Duration int32
|
||||
CronStr string
|
||||
AddTimes int32
|
||||
}
|
||||
|
||||
func NewLimitEventData(dataName string, dbName string, player *Player) *PlayerLimitData {
|
||||
act := &PlayerLimitData{
|
||||
PlayerData: NewPlayerData(dataName, player),
|
||||
MDbName: dbName,
|
||||
}
|
||||
|
||||
return act
|
||||
}
|
||||
|
||||
func CreateLimiteEventData(ID int32, dataName string, player *Player) PlayerDataModule {
|
||||
var data PlayerDataModule
|
||||
if ID == 1 {
|
||||
data = &PlayerChestRainData{PlayerLimitData: NewLimitEventData(dataName, "t_Limit_Chest_Rain", player)}
|
||||
}
|
||||
if ID == 2 {
|
||||
data = &PlayerSuperEmiterData{PlayerLimitData: NewLimitEventData(dataName, "t_Limit_Super_Emiter", player)}
|
||||
}
|
||||
if ID == 3 {
|
||||
data = &PlayerStarRainData{PlayerLimitData: NewLimitEventData(dataName, "t_Limit_Star_Rain", player)}
|
||||
}
|
||||
if ID == 4 {
|
||||
data = &PlayerHighRollerData{PlayerLimitData: NewLimitEventData(dataName, "t_Limit_High_Roller", player)}
|
||||
}
|
||||
if ID == 5 {
|
||||
data = &PlayerSuperOrderData{PlayerLimitData: NewLimitEventData(dataName, "t_Limit_Super_Order", player)}
|
||||
}
|
||||
if ID == 6 {
|
||||
data = &PlayerSceneSprintData{PlayerLimitData: NewLimitEventData(dataName, "t_Limit_Scene_Sprint", player)}
|
||||
}
|
||||
if ID == 7 {
|
||||
data = &PlayerCardFestivalData{PlayerLimitData: NewLimitEventData(dataName, "t_Limit_Card_Festival", player)}
|
||||
}
|
||||
if ID == 8 {
|
||||
data = &PlayerDoubleHitData{PlayerLimitData: NewLimitEventData(dataName, "t_Limit_Double_Hit", player)}
|
||||
}
|
||||
if ID == 9 {
|
||||
data = &PlayerCardSwapData{PlayerLimitData: NewLimitEventData(dataName, "t_Limit_Card_Swap", player)}
|
||||
}
|
||||
if ID == 10 {
|
||||
data = &PlayerPetRobberData{PlayerLimitData: NewLimitEventData(dataName, "t_Limit_Pet_Robber", player)}
|
||||
}
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
type LimiteEventManager struct {
|
||||
MStatus int32
|
||||
CronList map[int][]string
|
||||
IsSettle int32
|
||||
IsLoadDB bool
|
||||
MUpdateNotifyList []int32
|
||||
McronSave *cron.Cron
|
||||
McronSaveID cron.EntryID
|
||||
RobotCronID cron.EntryID
|
||||
RobotCronID10s cron.EntryID
|
||||
m_MapCronEntryIDs map[int][]*LimitEventPeriod
|
||||
Mdispatr *timer.Dispatcher
|
||||
IsHighRoll bool
|
||||
}
|
||||
|
||||
func (p *LimiteEventManager) GetLimitDataNameById(id int32) string {
|
||||
LimitDataMap := make(map[int32]string)
|
||||
LimitDataMap[1] = "PlayerChestRainData"
|
||||
LimitDataMap[2] = "PlayerSuperEmiterData"
|
||||
LimitDataMap[3] = "PlayerStarRainData"
|
||||
LimitDataMap[4] = "PlayerHighRollerData"
|
||||
LimitDataMap[5] = "PlayerSuperOrderData"
|
||||
LimitDataMap[6] = "PlayerSceneSprintData"
|
||||
LimitDataMap[7] = "PlayerCardFestivalData"
|
||||
LimitDataMap[8] = "PlayerDoubleHitData"
|
||||
LimitDataMap[9] = "PlayerCardSwapData"
|
||||
LimitDataMap[10] = "PlayerPetRobberData"
|
||||
|
||||
return LimitDataMap[id]
|
||||
}
|
||||
|
||||
func (p *LimiteEventManager) SaveDataFromDB(Key interface{}) bool {
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (p *LimiteEventManager) GetSunDayZero() int64 {
|
||||
timeStamp := time.Now().Unix()
|
||||
t := time.Unix(timeStamp, 0).Local()
|
||||
delta := int(t.Weekday()*3600*24) + t.Hour()*3600 + t.Minute()*60 + t.Second()
|
||||
return int64(timeStamp) - int64(delta)
|
||||
}
|
||||
|
||||
func (p *LimiteEventManager) GetLimitDataStatus(id int) *LimitEventPeriod {
|
||||
timeStamp := time.Now().Unix()
|
||||
keys := p.m_MapCronEntryIDs[id]
|
||||
for i := 0; i < len(keys); i++ {
|
||||
if timeStamp >= int64(keys[i].StartTime) && timeStamp < int64(keys[i].EndTime) {
|
||||
return keys[i]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *LimiteEventManager) GetIsHighRollerPersion() bool {
|
||||
return p.IsHighRoll
|
||||
}
|
||||
|
||||
// 1.宝箱雨
|
||||
func (p *LimiteEventManager) InitManager() {
|
||||
// 0 11 20 12 *
|
||||
p.IsHighRoll = false
|
||||
p.m_MapCronEntryIDs = map[int][]*LimitEventPeriod{}
|
||||
c := cron.New()
|
||||
LimiteCfg := gamedata.GetConfigByName("LimiteEvent")
|
||||
WeekZero := p.GetSunDayZero()
|
||||
timeStamp := time.Now().Unix()
|
||||
|
||||
p.Mdispatr = timer.NewDispatcher(10)
|
||||
for i := 0; i < LimiteCfg.NumRecord(); i++ {
|
||||
record := LimiteCfg.Record(i).(*gamedata.LimiteEvent)
|
||||
startStrr := record.StartTime
|
||||
starts := strings.Split(startStrr, "|")
|
||||
|
||||
DurStrr := record.Duration
|
||||
Durs := strings.Split(DurStrr, "|")
|
||||
|
||||
AddTimesStrr := record.AddTimes
|
||||
ats := strings.Split(AddTimesStrr, "|")
|
||||
|
||||
p.m_MapCronEntryIDs[record.Id] = []*LimitEventPeriod{}
|
||||
for n := 0; n < len(starts); n++ {
|
||||
LEP := &LimitEventPeriod{}
|
||||
start := starts[n]
|
||||
dur, _ := strconv.Atoi(Durs[n])
|
||||
addt, _ := strconv.Atoi(ats[n])
|
||||
LEP.StartCronID, _ = c.AddFunc(start, func() {
|
||||
fmt.Println("Next: UTC", c.Entry(LEP.StartCronID).Next.Unix())
|
||||
fmt.Println("CronStr:" + LEP.CronStr)
|
||||
cur := int32(time.Now().Unix())
|
||||
LEP.StartTime = int32(cur)
|
||||
LEP.EndTime = int32(cur) + int32(dur)
|
||||
if record.Id == 9 {
|
||||
if G_GameLogicPtr.M_SvrGlobal.LimitCardSwapTime < LEP.StartTime {
|
||||
card4Cfg, str4 := gamedata.GetRandomDifferenceSet(4, G_GameLogicPtr.M_SvrGlobal.Limit4CardExclude)
|
||||
card5Cfg, str5 := gamedata.GetRandomDifferenceSet(5, G_GameLogicPtr.M_SvrGlobal.Limit5CardExclude)
|
||||
G_GameLogicPtr.M_SvrGlobal.Limit4Card = int32(card4Cfg.Id)
|
||||
G_GameLogicPtr.M_SvrGlobal.Limit5Card = int32(card5Cfg.Id)
|
||||
G_GameLogicPtr.M_SvrGlobal.Limit4CardExclude = str4
|
||||
G_GameLogicPtr.M_SvrGlobal.Limit5CardExclude = str5
|
||||
G_GameLogicPtr.M_SvrGlobal.LimitCardSwapTime = LEP.StartTime
|
||||
db.FormatAllMemUpdateDb(&G_GameLogicPtr.M_SvrGlobal, "t_server_global_data", "Id")
|
||||
}
|
||||
}
|
||||
GoUtil.CallEvent(MergeConst.OpenNewLimitEvent, []interface{}{record.Id, cur, cur + int32(dur), record.Type})
|
||||
if record.Id == 4 {
|
||||
p.IsHighRoll = true
|
||||
}
|
||||
go func() {
|
||||
LeafTimer := p.Mdispatr.AfterFunc(time.Duration(dur)*time.Second, func() {
|
||||
if record.Id == 4 {
|
||||
p.IsHighRoll = false
|
||||
}
|
||||
})
|
||||
LEP.EndTimer = LeafTimer
|
||||
|
||||
(<-p.Mdispatr.ChanTimer).Cb()
|
||||
}()
|
||||
})
|
||||
LEP.Duration = int32(dur)
|
||||
LEP.CronStr = start
|
||||
LEP.AddTimes = int32(addt)
|
||||
p.m_MapCronEntryIDs[record.Id] = append(p.m_MapCronEntryIDs[record.Id], LEP)
|
||||
}
|
||||
}
|
||||
c.Start()
|
||||
for k, v := range p.m_MapCronEntryIDs {
|
||||
// record := LimiteCfg.Index(k).(*gamedata.LimiteEvent)
|
||||
key := k
|
||||
for i := 0; i < len(v); i++ {
|
||||
Schedule := c.Entry(v[i].StartCronID).Schedule
|
||||
Next := Schedule.Next(time.Unix(WeekZero, 0))
|
||||
// fmt.Println("Next.Unix():" + strconv.Itoa(int(Next.Unix())))
|
||||
value := v[i]
|
||||
if timeStamp >= Next.Unix() && timeStamp < Next.Unix()+int64(value.Duration) {
|
||||
fmt.Println("CronStr:" + value.CronStr)
|
||||
if key == 4 {
|
||||
p.IsHighRoll = true
|
||||
}
|
||||
if key == 9 {
|
||||
if G_GameLogicPtr.M_SvrGlobal.LimitCardSwapTime < int32(Next.Unix()) {
|
||||
card4Cfg, str4 := gamedata.GetRandomDifferenceSet(4, G_GameLogicPtr.M_SvrGlobal.Limit4CardExclude)
|
||||
card5Cfg, str5 := gamedata.GetRandomDifferenceSet(5, G_GameLogicPtr.M_SvrGlobal.Limit5CardExclude)
|
||||
G_GameLogicPtr.M_SvrGlobal.Limit4Card = int32(card4Cfg.Id)
|
||||
G_GameLogicPtr.M_SvrGlobal.Limit5Card = int32(card5Cfg.Id)
|
||||
G_GameLogicPtr.M_SvrGlobal.Limit4CardExclude = str4
|
||||
G_GameLogicPtr.M_SvrGlobal.Limit5CardExclude = str5
|
||||
G_GameLogicPtr.M_SvrGlobal.LimitCardSwapTime = int32(Next.Unix())
|
||||
db.FormatAllMemUpdateDb(&G_GameLogicPtr.M_SvrGlobal, "t_server_global_data", "Id")
|
||||
}
|
||||
}
|
||||
go func() {
|
||||
delta := Next.Unix() + int64(value.Duration) - timeStamp
|
||||
LeafTimer := p.Mdispatr.AfterFunc(time.Duration(delta)*time.Second, func() {
|
||||
if key == 4 {
|
||||
p.IsHighRoll = false
|
||||
}
|
||||
})
|
||||
value.EndTimer = LeafTimer
|
||||
value.StartTime = int32(Next.Unix())
|
||||
value.EndTime = int32(Next.Unix()) + int32(value.Duration)
|
||||
(<-p.Mdispatr.ChanTimer).Cb()
|
||||
}()
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,72 +0,0 @@
|
||||
package game
|
||||
|
||||
import (
|
||||
"server/GoUtil"
|
||||
"server/game/mod/limitedTimeEvent"
|
||||
"server/msg"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 限时事件触发器
|
||||
func LimitedTimeEventTrigger(p *Player, AddEventId int) {
|
||||
EndTime, TimeoutEvent, AddEvent := p.PlayMod.getLimitedTimeEventMod().Trigger()
|
||||
remainingTime := GoUtil.NextHourRemain()
|
||||
EndTime = GoUtil.IfTrue(EndTime > 0, min(EndTime, int(remainingTime)), int(remainingTime)).(int)
|
||||
if AddEventId != 0 {
|
||||
AddEvent = append(AddEvent, AddEventId)
|
||||
}
|
||||
if EndTime > 0 {
|
||||
p.CallEvent(time.Duration(EndTime)*time.Second, func() {
|
||||
p.lock.Lock()
|
||||
defer p.lock.Unlock()
|
||||
LimitedTimeEventTrigger(p, 0)
|
||||
p.SendClientRes()
|
||||
}, "LimitedTimeEvent")
|
||||
}
|
||||
|
||||
for _, v := range TimeoutEvent { // 事件到期处理
|
||||
p.PushClientRes(&msg.LimitEventNotify{
|
||||
Id: int32(v),
|
||||
Type: limitedTimeEvent.EVENT_NOTIFY_TYPE_DEL,
|
||||
})
|
||||
switch v {
|
||||
case limitedTimeEvent.EVENT_TYPE_HIGH_ROLLER:
|
||||
MaxEnergyMul := p.GetPlayerBaseMod().GetMaxEnergyMul()
|
||||
p.PlayMod.getBaseMod().ResetEnergyMul(MaxEnergyMul)
|
||||
p.PushClientRes(p.PlayMod.getBaseMod().BackData())
|
||||
case limitedTimeEvent.EVENT_TYPE_SUPER_ORDER:
|
||||
p.PlayMod.getOrderMod().RemoveSuperOrder()
|
||||
p.PushClientRes(p.PlayMod.getOrderMod().BackData())
|
||||
case limitedTimeEvent.EVENT_TYPE_CARD_FESTIVAL:
|
||||
p.PlayMod.getCardMod().ResetCardFestival()
|
||||
}
|
||||
}
|
||||
|
||||
for _, v := range AddEvent { // 增加事件处理
|
||||
switch v {
|
||||
case limitedTimeEvent.EVENT_TYPE_SUPER_ORDER:
|
||||
Emit := p.PlayMod.getChessMod().GetEmitList()
|
||||
Lv := p.GetPlayerBaseMod().GetLevel()
|
||||
p.PlayMod.getOrderMod().CreateSuperOrder(Lv, Emit)
|
||||
p.PushClientRes(p.PlayMod.getOrderMod().BackData())
|
||||
case limitedTimeEvent.EVENT_TYPE_CARD_FESTIVAL:
|
||||
p.PlayMod.getCardMod().CreateCardFestival()
|
||||
}
|
||||
}
|
||||
p.PushClientRes(p.PlayMod.getLimitedTimeEventMod().BackData())
|
||||
p.PlayMod.save()
|
||||
}
|
||||
|
||||
// 限时猪猪存钱罐触发器
|
||||
func LimitedTimePiggyBankTrigger(p *Player) {
|
||||
Remain := p.PlayMod.getPiggyBankMod().TimeOut()
|
||||
if Remain > 0 {
|
||||
p.CallEvent(time.Duration(Remain)*time.Second, func() {
|
||||
p.lock.Lock()
|
||||
defer p.lock.Unlock()
|
||||
p.PlayMod.getPiggyBankMod().TimeOut()
|
||||
p.SendClientRes()
|
||||
}, "PiggyBank")
|
||||
}
|
||||
p.PushClientRes(p.PlayMod.getPiggyBankMod().BackData())
|
||||
}
|
||||
@ -1,77 +0,0 @@
|
||||
package game
|
||||
|
||||
import (
|
||||
"server/db"
|
||||
"server/game/mod/item"
|
||||
"server/pkg/github.com/name5566/leaf/log"
|
||||
"sync"
|
||||
|
||||
"github.com/robfig/cron/v3"
|
||||
)
|
||||
|
||||
const (
|
||||
Login_log = 1
|
||||
LoginOut_log = 2
|
||||
Event_log = 3
|
||||
)
|
||||
|
||||
type LogMgr struct {
|
||||
L []*Log
|
||||
McronSave *cron.Cron
|
||||
Lock sync.Mutex
|
||||
}
|
||||
|
||||
type Log struct {
|
||||
Uid int32
|
||||
Type int32
|
||||
Event string
|
||||
Items []*item.Item
|
||||
TimeStamp int64
|
||||
}
|
||||
|
||||
func (L *LogMgr) InitManager() {
|
||||
L.McronSave = cron.New()
|
||||
L.L = make([]*Log, 0, 10)
|
||||
L.McronSave.AddFunc("@every 10s", func() {
|
||||
L.Lock.Lock()
|
||||
defer L.Lock.Unlock()
|
||||
for _, v := range L.L {
|
||||
switch v.Type {
|
||||
case Login_log:
|
||||
v.InsertLoginLog()
|
||||
case LoginOut_log:
|
||||
v.InsertLoginLog()
|
||||
case Event_log:
|
||||
v.InsertEventLog()
|
||||
default:
|
||||
log.Debug("unknown log type %d", v.Type)
|
||||
continue
|
||||
}
|
||||
}
|
||||
L.L = L.L[:0]
|
||||
})
|
||||
L.McronSave.Start()
|
||||
}
|
||||
|
||||
func (L *LogMgr) AddLog(logs *Log) {
|
||||
return
|
||||
L.Lock.Lock()
|
||||
defer L.Lock.Unlock()
|
||||
L.L = append(L.L, logs)
|
||||
}
|
||||
|
||||
func (Log *Log) InsertEventLog() {
|
||||
sqlStr := "INSERT INTO t_log_event (dwUin, type, event, timestamp) VALUES (?, ?, ?, ?)"
|
||||
_, err := db.SqlDb.Exec(sqlStr, Log.Uid, Log.Type, Log.Event, Log.TimeStamp)
|
||||
if err != nil {
|
||||
log.Debug("log insert event log error %s", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func (Log *Log) InsertLoginLog() {
|
||||
sqlStr := "INSERT INTO t_log_login (dwUin, type, event, timestamp) VALUES (?, ?, ?, ?)"
|
||||
_, err := db.SqlDb.Exec(sqlStr, Log.Uid, Log.Type, Log.Event, Log.TimeStamp)
|
||||
if err != nil {
|
||||
log.Debug("log insert event log error %s", err.Error())
|
||||
}
|
||||
}
|
||||
@ -1,72 +0,0 @@
|
||||
package game
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"server/GoUtil"
|
||||
"server/db"
|
||||
"server/game/mod/item"
|
||||
"server/game/mod/msg"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type MailMgr struct {
|
||||
*ServerMod
|
||||
list map[int]*ServerMail
|
||||
}
|
||||
|
||||
type MailData struct {
|
||||
List map[int][]*msg.Msg
|
||||
}
|
||||
|
||||
type ServerMail struct {
|
||||
Id int
|
||||
Title string
|
||||
Content string
|
||||
Items []*item.Item
|
||||
Start_time int64
|
||||
Register_time int64
|
||||
End_time int64
|
||||
Mail_type int
|
||||
To_uids []int
|
||||
}
|
||||
|
||||
func (m *MailMgr) Init() {
|
||||
m.key = MAIL_MGR_KEY
|
||||
m.data = &MailData{
|
||||
List: make(map[int][]*msg.Msg),
|
||||
}
|
||||
m.list = make(map[int]*ServerMail)
|
||||
// 注册处理函数
|
||||
m.init()
|
||||
m.LoadMail()
|
||||
}
|
||||
|
||||
func (r *MailMgr) LoadMail() {
|
||||
// 从数据库加载邮件
|
||||
data := make([]*db.SqlServerMailStruct, 0)
|
||||
db.GetServerMailData(&data)
|
||||
for _, v := range data {
|
||||
Uids := make([]int, 0)
|
||||
UidArr := strings.Split(v.To_uids, ",")
|
||||
for _, v := range UidArr {
|
||||
Uids = append(Uids, GoUtil.Int(v))
|
||||
}
|
||||
var items []interface{}
|
||||
json.Unmarshal([]byte(v.Items), &items)
|
||||
r.list[v.Id] = &ServerMail{
|
||||
Id: v.Id,
|
||||
Title: v.Title,
|
||||
Content: v.Content,
|
||||
Items: item.ParseItem(items),
|
||||
Start_time: v.Start_time,
|
||||
Register_time: v.Register_time,
|
||||
End_time: v.End_time,
|
||||
Mail_type: v.Mail_type,
|
||||
To_uids: Uids,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (r *MailMgr) Sync() {
|
||||
G_GameLogicPtr.NotifyAll(&msg.Msg{Type: msg.HANDLE_TYPE_MAIL, Extra: r.list[1]})
|
||||
}
|
||||
@ -1,9 +0,0 @@
|
||||
package game
|
||||
|
||||
type PlayerSimpleData struct {
|
||||
Uid int
|
||||
Name string
|
||||
Avatar int
|
||||
Level int
|
||||
Face int
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,113 +0,0 @@
|
||||
package game
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"server/db"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type OldPlayerCompensateMgr struct {
|
||||
MSqlCompensateStruct map[string]*db.SqlCompensateStruct
|
||||
}
|
||||
|
||||
func (p *OldPlayerCompensateMgr) SuccessSendEmail(username string) bool {
|
||||
|
||||
emailst, ok := p.MSqlCompensateStruct[username]
|
||||
if ok {
|
||||
emailst.IsSendEmail = 1
|
||||
db.FormatAllMemUpdateDb(emailst, "t_player_compensate_Data", "auto_id")
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *OldPlayerCompensateMgr) SendEmailToDb(username string, dwUin int32) bool {
|
||||
|
||||
emailst, ok := p.MSqlCompensateStruct[username]
|
||||
if ok {
|
||||
if emailst.IsSendEmail == 1 {
|
||||
return false
|
||||
} else {
|
||||
sqlSt := &db.SqlEmailStruct{}
|
||||
sqlSt.DwUin = dwUin
|
||||
sqlSt.Content = `Welcome back to our game!
|
||||
Here comes your refund for your scene progress and payment in test version!
|
||||
Have fun in new version!`
|
||||
sqlSt.CurrencyCount = 0
|
||||
sqlSt.CurrencyInfo = ""
|
||||
sqlSt.RecvTime = 0
|
||||
sqlSt.Title = "Test Players' Refund"
|
||||
sqlSt.Sender = "System"
|
||||
sqlSt.ItemCount = 0
|
||||
sqlSt.ItemInfo = ""
|
||||
sqlSt.SendTime = int32(time.Now().Unix())
|
||||
sqlSt.Status = 0
|
||||
sqlSt.Type = 1
|
||||
sqlSt.RewardId = ""
|
||||
sqlSt.RewardCount = ""
|
||||
sqlSt.LinkUrl = ""
|
||||
strarr := []string{}
|
||||
if emailst.DecorationCnt-5 > 0 {
|
||||
SceneDiamond := (emailst.DecorationCnt-5)*10 + 25
|
||||
|
||||
temp := fmt.Sprintf("Diamond|%d", SceneDiamond)
|
||||
strarr = append(strarr, temp)
|
||||
}
|
||||
f, err := strconv.ParseFloat(emailst.ChargeCnt, 64)
|
||||
var ChargeDiamond float64 = 0
|
||||
if err == nil {
|
||||
ChargeDiamond = f * 1.5 * 75
|
||||
}
|
||||
if ChargeDiamond > 0 {
|
||||
cd := int32(math.Ceil(ChargeDiamond))
|
||||
remain := cd % 10
|
||||
if remain != 0 && remain != 5 {
|
||||
if remain < 5 {
|
||||
cd = cd - remain + 5
|
||||
} else {
|
||||
cd = cd - remain + 10
|
||||
}
|
||||
}
|
||||
temp := fmt.Sprintf("Diamond|%d", cd)
|
||||
strarr = append(strarr, temp)
|
||||
|
||||
}
|
||||
sqlSt.RewardType = strings.Join(strarr, "_")
|
||||
|
||||
insertId, err1 := db.FormatAllMemInsertDb(sqlSt, "system_mail_info")
|
||||
|
||||
if err1 == nil {
|
||||
p.SuccessSendEmail(username)
|
||||
fmt.Sprintln("Success Intert Mail:" + strconv.Itoa(int(insertId)))
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *OldPlayerCompensateMgr) LoadData() {
|
||||
sqlStr := "SELECT * FROM t_player_compensate_Data"
|
||||
sqlStrucks := []db.SqlCompensateStruct{}
|
||||
|
||||
p.MSqlCompensateStruct = make(map[string]*db.SqlCompensateStruct)
|
||||
if err := db.SqlDb.Select(&sqlStrucks, sqlStr); err != nil {
|
||||
fmt.Printf("get data failed, err:%v\n", err)
|
||||
return
|
||||
} else {
|
||||
|
||||
}
|
||||
for i := 0; i < len(sqlStrucks); i++ {
|
||||
p.MSqlCompensateStruct[sqlStrucks[i].DeviceId] = &sqlStrucks[i]
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (p *OldPlayerCompensateMgr) InitManager() {
|
||||
p.LoadData()
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user