Compare commits
702 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a1a7285df0 | |||
| cd73603e3f | |||
| ed3091994d | |||
| 4bd22c1e91 | |||
| b630df850f | |||
| da99cad206 | |||
| 22027b5fdd | |||
| 7f00c4183f | |||
| 2bde2fd8ac | |||
| 48a48f0c07 | |||
| a70d1d7268 | |||
| 5cc4167e4f | |||
| b9e2514556 | |||
| 0b11781329 | |||
| 645d11ea54 | |||
| 3e87b9f44a | |||
| a6dc4514f2 | |||
| 69ea9a1d43 | |||
| 1dfbbb543c | |||
| 092df678a8 | |||
| 5f165eed75 | |||
| a988422302 | |||
| e5f6e31af2 | |||
| f4bd83e86a | |||
| 7713ee499d | |||
| 6fb2d93650 | |||
| 81db29f76f | |||
| fd2018186c | |||
| bb85a7c619 | |||
| 9e7e90db6c | |||
| 007e01156b | |||
| d2ec62ac7f | |||
| da32bdec94 | |||
| 7d58e90557 | |||
| 08dabda7c7 | |||
| feea348ec3 | |||
| 67eb7dee0f | |||
| 6fb1d2855e | |||
| faa3d9320c | |||
| 497cd543fd | |||
| 71d5205df0 | |||
| bba90d93f1 | |||
| ab40b1b82d | |||
| 22a6cefbdc | |||
| 9ca3a24862 | |||
| 91f0dfa5c5 | |||
| f0e935a5d8 | |||
| f0fae0fce0 | |||
| 4c40ba36a6 | |||
| bd7a25560f | |||
| e02659d850 | |||
| c95f96572c | |||
| 1c1356a4d1 | |||
| f206deb8ed | |||
| 9bf6aae8e9 | |||
| 63bfc7a5c1 | |||
| 731c6477a5 | |||
| e0bf35284c | |||
| 02ebb0b0ab | |||
| 92741daaa8 | |||
| 18ce05d07d | |||
| 37e6e9feb6 | |||
| 655c5ca42c | |||
| c99fc5c389 | |||
| 9b0a4a003e | |||
| f25610c90b | |||
| 7130d3989c | |||
| 900d2bd2e9 | |||
| 7d255dfa30 | |||
| 0cce930260 | |||
| 0671a54b20 | |||
| 4df4a1fa4b | |||
| 5b52a0ff00 | |||
| 5186d09116 | |||
| a5b06bbd07 | |||
| 9b74cb5a00 | |||
| 280e441227 | |||
| be97e7faa0 | |||
| 253822a056 | |||
| 0fcc45039d | |||
| 4700e2ae90 | |||
| d9c89e1dc6 | |||
| 2080e227ef | |||
| b513fd37cb | |||
| a89358e362 | |||
| 5c91e6083d | |||
| 276e87c5e7 | |||
| 45eabafacc | |||
| 6664612b73 | |||
| 82ed075ee8 | |||
| c7dc203687 | |||
| 304eca4b6a | |||
| 13315e6132 | |||
| 90684451d8 | |||
| 799849920f | |||
| f7d83f1459 | |||
| fbf5f32415 | |||
| e922422922 | |||
| b9648393a7 | |||
| d20cc6514b | |||
| 6a20976370 | |||
| 3e56aacb4e | |||
| a8e18d1bb8 | |||
| 32ed70f099 | |||
| e89b6182a7 | |||
| 41d04c7604 | |||
| d7a5869e99 | |||
| 3139902b37 | |||
| dc599fe5c3 | |||
| 5829bfeaa2 | |||
| 100805da8b | |||
| 0679087e53 | |||
| b6476dcb79 | |||
| 471e1c0d2c | |||
| 3d6b1a059c | |||
| f56ca830cf | |||
| 0fbe7d99cb | |||
| bbdf64415c | |||
| 5981af630a | |||
| 7e14bd8675 | |||
| 0f407f9658 | |||
| 9439098472 | |||
| 6618c004c3 | |||
| 18ab6623ff | |||
| 2fe0da569b | |||
| 42e907580c | |||
| ae76066db6 | |||
| 5c74580866 | |||
| 2dd5ebcb8c | |||
| 69f3d9838d | |||
| e8010782fd | |||
| 4e54d86712 | |||
| fdc0d31632 | |||
| 0d903d23b0 | |||
| e79036d42f | |||
| 39e94c6ea7 | |||
| 0c10cb0ead | |||
| 7301a22d44 | |||
| 89817d420c | |||
| c53f622e94 | |||
| eb43dc3960 | |||
| 6001ee6979 | |||
| d09e545554 | |||
| 642270e4c3 | |||
| d648725b10 | |||
| 0f6ecb8f03 | |||
| ce60648233 | |||
| 186860c1fa | |||
| 3beed667b4 | |||
| 2219dd55dd | |||
| 3e73a5090a | |||
| 583a275100 | |||
| a4c1dd6f5b | |||
| de69919c01 | |||
| 6dea065ed2 | |||
| 9e208532d3 | |||
| c0b6d87678 | |||
| 778edac895 | |||
| 17d1cf1665 | |||
| 3f3671c95c | |||
| 52c06917c3 | |||
| b2ea5cbef8 | |||
| 99c7466b37 | |||
| e60c18d8a8 | |||
| 8c4da6288e | |||
| 1a73adf414 | |||
| cb76ae01e1 | |||
| 89df4e451c | |||
| f99b4bd0ad | |||
| 930f889745 | |||
| fe39310eca | |||
| b9790d458e | |||
| dc8d5f741a | |||
| b3288e9c72 | |||
| c88aa79377 | |||
| 2327c07f9a | |||
| 8e93d4cd19 | |||
| a963bde749 | |||
| 10b6997c32 | |||
| 970c77678b | |||
| 07c479746b | |||
| d90a8a36cf | |||
| c1eee8e139 | |||
| dd831a65a5 | |||
| 51783604c6 | |||
| 9f8471d4e9 | |||
| c4ac2601ad | |||
| b4a0994871 | |||
| b619e1dac5 | |||
| ba1703c684 | |||
| 131b5b7805 | |||
| 099415e823 | |||
| 91261f4315 | |||
| 548be5042d | |||
| e9fd7fd80f | |||
| e44cd3edc6 | |||
| 219a7a3493 | |||
| 6876a6dd9f | |||
| d04a69f481 | |||
| dfa8317706 | |||
| 555514f7dd | |||
| 74633937bc | |||
| 948736b5ea | |||
| 5e54b8b105 | |||
| 0d818dd00f | |||
| 22586e601f | |||
| 9938df3c28 | |||
| ec2e8d3654 | |||
| 71a9c0c98f | |||
| 54cef57ea5 | |||
| 73c1116047 | |||
| abb85f005d | |||
| 5e91ee9844 | |||
| 8e781651a9 | |||
| 74db202cd9 | |||
| 26b3b3ea78 | |||
| bfc2197089 | |||
| 49c515169e | |||
| d9c04a58c0 | |||
| 57be7b2dfe | |||
| 07b62d4bf2 | |||
| 726aead1c1 | |||
| a1af29dff9 | |||
| 388e80ee92 | |||
| 7d09faf528 | |||
| f2876d79fb | |||
| 1155bed754 | |||
| c6278b17e9 | |||
| 3a0d5f6347 | |||
| 7e6d511ae4 | |||
| f35ac01399 | |||
| 64807852ff | |||
| 342d9c96ee | |||
| eaa0cdd600 | |||
| 7507fb9ea2 | |||
| 839e192711 | |||
| 2ad33f4567 | |||
| 8db573a789 | |||
| c50a413fcd | |||
| 6a96d993e1 | |||
| a93f0546e3 | |||
| a18a6bd3a5 | |||
| 2f5c423e53 | |||
| ba1bc04b9c | |||
| 6d1790a02e | |||
| 598c6736a6 | |||
| 44e4790e45 | |||
| 409eb21b85 | |||
| 54872f102d | |||
| b1c655bbc7 | |||
| 50219cc4a9 | |||
| 01e46b566a | |||
| 93c97cf94b | |||
| 8e9b580745 | |||
| 70104d73aa | |||
| aa3e56f98f | |||
| eee560a7fe | |||
| e8a1c33d40 | |||
| abeaa249b8 | |||
| 797905d050 | |||
| 797aadb328 | |||
| 4c918925d8 | |||
| 640eb9335e | |||
| cdce697ae6 | |||
| ef85e2de25 | |||
| 3128b821f4 | |||
| 233f0b107a | |||
| 772103d81d | |||
| 0ad235ccc1 | |||
| 61d41c3ac8 | |||
| 5ecc6adf8f | |||
| a8e4489ae7 | |||
| a7888c0c67 | |||
| 8932c71173 | |||
| 1f734f4b95 | |||
| fe06f06a11 | |||
| 3a8bd1d826 | |||
| 9f6199b8f2 | |||
| 3bf95f6eba | |||
| 4f88d15f8e | |||
| 1c759b2476 | |||
| 6f104f0b2e | |||
| 9b4b4634c3 | |||
| 7dc331eb07 | |||
| 059320e5f1 | |||
| 41a97ef3aa | |||
| f52f466e53 | |||
| c2d726e9a6 | |||
| 0d77a9745e | |||
| 48d5add08b | |||
| b40df54c9a | |||
| 4d65dd2a3a | |||
| c5a4dfed03 | |||
| e8d74f559d | |||
| e2c848a737 | |||
| 625276a64f | |||
| bf5b3f8358 | |||
| 86a9075d04 | |||
| 6acc1c0da8 | |||
| 457997a430 | |||
| a3d0238e10 | |||
| 0aed8ff2d7 | |||
| 6a8f81f871 | |||
| 90e3f8e5f2 | |||
| d8a316dddd | |||
| c4d567186e | |||
| 6ef4f0f3e3 | |||
| bb9c46b147 | |||
| 131d2429f9 | |||
| d305fe6679 | |||
| 35c801ae63 | |||
| b5a46d94de | |||
| 5a5992b353 | |||
| f56a23f4b7 | |||
| a57382f269 | |||
| 9380efdd3d | |||
| ad64370bf1 | |||
| 54bae76d27 | |||
| 93f1385c7a | |||
| d5dbc7e5c7 | |||
| 72bbb4ebaa | |||
| caf0d3f8ed | |||
| 95726cc7f9 | |||
| ca7a070e4c | |||
| ab1d952070 | |||
| 1ce64bbcdf | |||
| 1c38384ac7 | |||
| 90ff68eacd | |||
| f7569f3eb1 | |||
| 77c289dc13 | |||
| cca78be983 | |||
| c15575cb54 | |||
| 81dd695999 | |||
| 3065b98456 | |||
| e3c460e614 | |||
| a1cb16dd3d | |||
| e9810c69f4 | |||
| 2b0bee198e | |||
| c31e009860 | |||
| 2b94776e71 | |||
| fe2b877052 | |||
| efad796eb0 | |||
| fe17b93bde | |||
| af9aa5c1cb | |||
| 5e39bd0bd3 | |||
| ac5dfcde26 | |||
| 8aef3ceb06 | |||
| 5155ab6302 | |||
| cd5a008637 | |||
| 58fe9a7394 | |||
| 910ebdd5bf | |||
| 5f89964f49 | |||
| 4f0bc6d12f | |||
| 9346285c08 | |||
| 19a4ec3176 | |||
| 46f64d8048 | |||
| e04608e499 | |||
| c402e2ec5a | |||
| 4437be8863 | |||
| b54c1f8d34 | |||
| a9402846b5 | |||
| c37e4b2374 | |||
| acad03fbbf | |||
| 8061645346 | |||
| b97840a320 | |||
| a5ba77a3d2 | |||
| ea383dd0f1 | |||
| 885db23fc6 | |||
| 68ab92dd7a | |||
| d9495ff839 | |||
| 0e01d8145f | |||
| ed9e379500 | |||
| a9cb2d2490 | |||
| 900937c033 | |||
| 9585fc1bdb | |||
| d8d3e8544c | |||
| a50e5fa802 | |||
| c9363ca6e8 | |||
| 222bd879d1 | |||
| 01f4a8f205 | |||
| be976b6738 | |||
| c89a818696 | |||
| 1c63eca0f7 | |||
| 69989fb99e | |||
| 8cf794e303 | |||
| de9e74d616 | |||
| e147a25076 | |||
| b25d874122 | |||
| b322032757 | |||
| d505601d33 | |||
| 8580d57a12 | |||
| b051f4feef | |||
| 96c886b93d | |||
| f1d6df9a17 | |||
| 6681075031 | |||
| 1aae25f510 | |||
| 8a5dfc8e6a | |||
| 9daf44d512 | |||
| 2485514111 | |||
| 528b61c5d9 | |||
| 829f7180da | |||
| 18203574d0 | |||
| b2678d3165 | |||
| eb7c98c302 | |||
| a8ef8f3f3e | |||
| d49f75427f | |||
| 1621559f7e | |||
| d7f3afbb5f | |||
| a670e4a64a | |||
| 12f7c63ed5 | |||
| 32939b1383 | |||
| 14e5b7d5a7 | |||
| f994adc45d | |||
| d6a7bbe054 | |||
| d017202c36 | |||
| 9eb4df5ceb | |||
| 16c0a8a81b | |||
| 7fa7d17ba6 | |||
| 7bbdce13ea | |||
| 6c6fd229c3 | |||
| 54dfde335a | |||
| f04b60c0c8 | |||
| 4d6894b14b | |||
| 82215acee4 | |||
| a78c447d46 | |||
| 6342d5b69f | |||
| c6f5430f0c | |||
| 1dd071306a | |||
| 5816dfecc0 | |||
| fc83a912d7 | |||
| 71e9361ae9 | |||
| 636238a2a4 | |||
| 03bcf18224 | |||
| 917ccf7b7d | |||
| 0b7ec2d07c | |||
| a6472a85ff | |||
| a2b1408b8d | |||
| abcbcf0ac8 | |||
| 0bf21a86fe | |||
| 95e55b1c1c | |||
| a9e36e50a3 | |||
| f1f6edd848 | |||
| 89b0d59ab9 | |||
| b1f1dff01a | |||
| e5ccb29823 | |||
| 79e2c340b1 | |||
| 827cd17835 | |||
| ac855f9a83 | |||
| 6ffdc4d2b6 | |||
| 44f9c75f41 | |||
| e0cc4e0790 | |||
| 1d9e1cb033 | |||
| e413760b32 | |||
| 72f0055c58 | |||
| 4260b9d1ec | |||
| 4eee83ca6f | |||
| 5cbbe5fc61 | |||
| a542a35eba | |||
| 00e34c21e1 | |||
| cf718a4cbd | |||
| 5b037221a7 | |||
| bee35c4ebf | |||
| 3c364edbe1 | |||
| 98fee693a4 | |||
| 2734c3e58e | |||
| 6d7c928197 | |||
| 0635e67e93 | |||
| b4df964d79 | |||
| 36e8f7691a | |||
| 94803c4ff1 | |||
| 4886e3464f | |||
| 352ab899d4 | |||
| 23306d1f5c | |||
| fc546ac87a | |||
| 764b2788ae | |||
| d1fc832d2d | |||
| c170c70639 | |||
| 8db8d0f6da | |||
| 6b5e0b82ba | |||
| 265ea66894 | |||
| b1b4bb0a79 | |||
| fa7ce8bfb4 | |||
| 78369644c7 | |||
| 22b8b6bf64 | |||
| fcec8e41a2 | |||
| ee24cabbed | |||
| eed1c5aedc | |||
| 1f88b3bc12 | |||
| 5cd8791fee | |||
| 787e04488b | |||
| 2accd9592c | |||
| 66bfbbbdb1 | |||
| cb195fd1ca | |||
| a1ef28095f | |||
| 77b40cc1e8 | |||
| 4c52484fd7 | |||
| 5b72708167 | |||
| b69e931c44 | |||
| 213b1c2702 | |||
| 0fef595229 | |||
| 791d1f1872 | |||
| ef92c776af | |||
| 66cf0143f6 | |||
| 3ff3b0d294 | |||
| b9ecb58760 | |||
| a8e55b4ae3 | |||
| 657e51f2cc | |||
| ff16f91311 | |||
| d05d4971b5 | |||
| 5f58e92666 | |||
| a31c2f45b1 | |||
| 06d9e71ae8 | |||
| 441e020192 | |||
| f153867d85 | |||
| eed5ce1b7b | |||
| 00b4bcb6a3 | |||
| e69ba501da | |||
| f2ccbf72a8 | |||
| c29aec210b | |||
| 78b5102692 | |||
| 9fd671db85 | |||
| beb99418d4 | |||
| 0f70de9a5a | |||
| 08ad55c742 | |||
| a70c1e0102 | |||
| efec997128 | |||
| 413c2a39d7 | |||
| 5a9b9ce619 | |||
| ee58da2b39 | |||
| 7475cd8ea4 | |||
| 8b8f6c0e2e | |||
| 69b170b754 | |||
| 702b6aae32 | |||
| 010874586a | |||
| fcc34c28aa | |||
| ecbc11cf0b | |||
| bfd3a8f439 | |||
| f8dd410d96 | |||
| 2459aec4b6 | |||
| d623337a15 | |||
| 73c3cea778 | |||
| 11a4cff10a | |||
| 628d5adcb5 | |||
| 8681cd0733 | |||
| bb2fdbfb40 | |||
| 4dedc30d94 | |||
| fa995eea53 | |||
| e819be918b | |||
| 1e3e625c1a | |||
| b747a4bdff | |||
| 03443104be | |||
| 819e55e235 | |||
| 80b06f3bc7 | |||
| d90e87896c | |||
| 72073b80f0 | |||
| 19866bc4a4 | |||
| cf4037614a | |||
| 5c22601c52 | |||
| 1bb3bb1fa7 | |||
| 11959ca794 | |||
| 9ba9af6369 | |||
| 584f2074fd | |||
| 2971a0a202 | |||
| 3cc8128faa | |||
| 1ef7ed4b3f | |||
| 59eabe38c6 | |||
| 1c090a5a65 | |||
| 82fade61d5 | |||
| fc5009bf0d | |||
| 9fe91fe22c | |||
| 37d327bcb6 | |||
| 217b411095 | |||
| 9239f3a90d | |||
| ae9d9ea159 | |||
| 12cfd243f6 | |||
| 059c00c2ad | |||
| 3dab24c142 | |||
| 4de55f9cf6 | |||
| 07d9bbbf7c | |||
| c182510a46 | |||
| aec1277ab3 | |||
| 32b694cbb0 | |||
| 932368f2d6 | |||
| 7a33fc8928 | |||
| d048db44ba | |||
| 76b92bacd9 | |||
| dadae42992 | |||
| 1e9058a5cb | |||
| b307911896 | |||
| 11a1547242 | |||
| 17ee5dc97b | |||
| ac89630f5d | |||
| 94028484cf | |||
| 1b1fd77470 | |||
| 7a7b148a7d | |||
| e6cee92ef1 | |||
| 31123081c7 | |||
| b5b435d398 | |||
| 395f8f825f | |||
| c71bd9f3a8 | |||
| 3e971c3dfd | |||
| 3f372d9228 | |||
| d385093403 | |||
| f978b285ae | |||
| 1eeaa442db | |||
| 14cc0abdc5 | |||
| d5ce692933 | |||
| 56a7b90c99 | |||
| 9352e7f32e | |||
| 0fc2f61a42 | |||
| 25249125b1 | |||
| 9d6d325fa6 | |||
| 0d408ede47 | |||
| 36bc761c19 | |||
| 9c3f0b0142 | |||
| e6be595c16 | |||
| dd4739a822 | |||
| 39254506bf | |||
| 227d93d756 | |||
| d223f316d6 | |||
| b6ec553dcb | |||
| cc6a9c38bd | |||
| 04ad3adbd1 | |||
| ef3804bf4e | |||
| b5d3408773 | |||
| 470f5ff28f | |||
| 888ee7235b | |||
| c97eda6672 | |||
| 81478f203c | |||
| ec51635d44 | |||
| aae15fba60 | |||
| 57fad7e113 | |||
| 1c25908a04 | |||
| 84a8137955 | |||
| 038d4c1850 | |||
| 0ffe2c2fc9 | |||
| 401933038d | |||
| 5cf88f308a | |||
| 29df796c48 | |||
| 79af85667e | |||
| 57237f6dfa | |||
| fc86e3ef78 | |||
| 846b7f67e5 | |||
| ffe3f5d24a | |||
| 2db1a15c72 | |||
| 95342ae054 | |||
| 6800356f10 | |||
| 95b5d88197 | |||
| 9f6f55d8e8 | |||
| d1ebcfeef0 | |||
| 5305bf0bfd | |||
| 78c5ab5d8a | |||
| 836c568fef | |||
| 7cbd1ebae7 | |||
| a35a277b32 | |||
| 9b93e0e4b6 | |||
| 65a272d6cb | |||
| 971f0f7683 | |||
| d2718c1934 | |||
| 0cdd2b20d6 | |||
| 66b2bf8436 | |||
| cf01767ad3 | |||
| fdefdb88cc | |||
| 4bcc992b7f | |||
| 35aba2207b | |||
| ce2ee9e0fb | |||
| 9093ad2d9f | |||
| 08ed6504f2 | |||
| 9f70748b55 | |||
| 3f6a7ce48f | |||
| ed320196fe | |||
| 62f27f8231 | |||
| c3485903c5 | |||
| 5f3089b61b | |||
| e8f42ab669 | |||
| e3ff584bf4 | |||
| a9116a2f28 | |||
| 2de4a60f3a | |||
| 79309c3c05 | |||
| 80c1c2edac | |||
| f098cc0762 | |||
| ddd8c44396 | |||
| 6edcfa993e | |||
| e63764e2cf | |||
| a1b4ccb736 | |||
| 63540088c9 | |||
| 550b3a1b69 | |||
| 7bfb79f4dd | |||
| 44b255512d | |||
| 7a76050cc7 | |||
| e11f36412f | |||
| abcd2640bb | |||
| 974e6780a5 | |||
| b6bf9dabcc | |||
| 642ff72ee0 | |||
| f24d6c5b5f | |||
| df6931d4b1 | |||
| 793ab1d75b | |||
| db04fd2a5b | |||
| 2e3448ab58 | |||
| c4d1c41059 | |||
| ca6e301d46 |
-203
@@ -1,203 +0,0 @@
|
|||||||
<?xml version="1.0"?>
|
|
||||||
<!DOCTYPE module PUBLIC
|
|
||||||
"-//Puppy Crawl//DTD Check Configuration 1.3//EN"
|
|
||||||
"http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
|
|
||||||
<!--
|
|
||||||
Note: Checkstyle likes to introduce breaking changes like removing support for certain properties. Since this
|
|
||||||
configuration is also used by CodeClimate, we should keep it in sync with the version that they use:
|
|
||||||
https://github.com/codeclimate/codeclimate-checkstyle/blob/master/bin/install-checkstyle.sh
|
|
||||||
https://docs.codeclimate.com/docs/checkstyle (currently outdated)
|
|
||||||
-->
|
|
||||||
|
|
||||||
<module name="Checker">
|
|
||||||
<property name="charset" value="UTF-8"/>
|
|
||||||
<property name="severity" value="warning"/>
|
|
||||||
<property name="fileExtensions" value="java"/>
|
|
||||||
|
|
||||||
<module name="SuppressWarningsFilter" />
|
|
||||||
|
|
||||||
<module name="LineLength">
|
|
||||||
<property name="max" value="120"/>
|
|
||||||
<property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://"/>
|
|
||||||
</module>
|
|
||||||
|
|
||||||
<module name="TreeWalker">
|
|
||||||
<module name="SuppressWarningsHolder"/>
|
|
||||||
<module name="OuterTypeFilename"/>
|
|
||||||
<module name="IllegalTokenText">
|
|
||||||
<property name="tokens" value="STRING_LITERAL, CHAR_LITERAL"/>
|
|
||||||
<property name="format" value="\\u00(08|09|0(a|A)|0(c|C)|0(d|D)|22|27|5(C|c))|\\(0(10|11|12|14|15|42|47)|134)"/>
|
|
||||||
<property name="message" value="Avoid using corresponding octal or Unicode escape."/>
|
|
||||||
</module>
|
|
||||||
<module name="AvoidEscapedUnicodeCharacters">
|
|
||||||
<property name="allowEscapesForControlCharacters" value="true"/>
|
|
||||||
<property name="allowByTailComment" value="true"/>
|
|
||||||
<property name="allowNonPrintableEscapes" value="true"/>
|
|
||||||
</module>
|
|
||||||
<module name="TodoComment">
|
|
||||||
<!-- Allow comments which have an issue number as they are accounted for in the issue tracker -->
|
|
||||||
<property name="format" value="TODO(?! #\d+:)|FIXME"/>
|
|
||||||
</module>
|
|
||||||
<module name="GenericWhitespace"/>
|
|
||||||
<module name="WhitespaceAfter"/>
|
|
||||||
<module name="AvoidStarImport"/>
|
|
||||||
<module name="RedundantImport"/>
|
|
||||||
<module name="UnusedImports"/>
|
|
||||||
<module name="OneTopLevelClass"/>
|
|
||||||
<module name="FinalClass"/>
|
|
||||||
<module name="HideUtilityClassConstructor"/>
|
|
||||||
<module name="InnerTypeLast"/>
|
|
||||||
<module name="VisibilityModifier"/>
|
|
||||||
<module name="AvoidNestedBlocks"/>
|
|
||||||
<module name="NoLineWrap"/>
|
|
||||||
<module name="EmptyBlock">
|
|
||||||
<property name="option" value="TEXT"/>
|
|
||||||
<property name="tokens" value="LITERAL_TRY, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE, LITERAL_SWITCH"/>
|
|
||||||
</module>
|
|
||||||
<module name="NeedBraces"/>
|
|
||||||
<module name="RightCurly"/>
|
|
||||||
<module name="RightCurly">
|
|
||||||
<property name="option" value="alone"/>
|
|
||||||
<property name="tokens" value="CLASS_DEF, METHOD_DEF, CTOR_DEF, LITERAL_FOR, LITERAL_WHILE, LITERAL_DO, STATIC_INIT, INSTANCE_INIT"/>
|
|
||||||
</module>
|
|
||||||
<module name="OneStatementPerLine"/>
|
|
||||||
<module name="MultipleVariableDeclarations"/>
|
|
||||||
<module name="ArrayTypeStyle"/>
|
|
||||||
<module name="MissingSwitchDefault"/>
|
|
||||||
<module name="DefaultComesLast"/>
|
|
||||||
<module name="FallThrough"/>
|
|
||||||
<module name="NestedTryDepth"/>
|
|
||||||
<module name="UpperEll"/>
|
|
||||||
<module name="ModifierOrder"/>
|
|
||||||
<module name="RedundantModifier"/>
|
|
||||||
<module name="EmptyLineSeparator">
|
|
||||||
<property name="allowNoEmptyLineBetweenFields" value="true"/>
|
|
||||||
</module>
|
|
||||||
<module name="SeparatorWrap">
|
|
||||||
<property name="tokens" value="DOT"/>
|
|
||||||
<property name="option" value="nl"/>
|
|
||||||
</module>
|
|
||||||
<module name="SeparatorWrap">
|
|
||||||
<property name="tokens" value="COMMA"/>
|
|
||||||
<property name="option" value="EOL"/>
|
|
||||||
</module>
|
|
||||||
<module name="PackageName">
|
|
||||||
<property name="format" value="^[a-z]+(\.[a-z][a-z0-9]*)*$"/>
|
|
||||||
<message key="name.invalidPattern"
|
|
||||||
value="Package name ''{0}'' must match pattern ''{1}''."/>
|
|
||||||
</module>
|
|
||||||
<module name="TypeName">
|
|
||||||
<message key="name.invalidPattern"
|
|
||||||
value="Type name ''{0}'' must match pattern ''{1}''."/>
|
|
||||||
</module>
|
|
||||||
<module name="MemberName">
|
|
||||||
<property name="format" value="^[a-z][a-zA-Z0-9]*$"/>
|
|
||||||
<message key="name.invalidPattern"
|
|
||||||
value="Member name ''{0}'' must match pattern ''{1}''."/>
|
|
||||||
</module>
|
|
||||||
<module name="ParameterName">
|
|
||||||
<property name="format" value="^[a-z][a-zA-Z0-9]*$"/>
|
|
||||||
<message key="name.invalidPattern"
|
|
||||||
value="Parameter name ''{0}'' must match pattern ''{1}''."/>
|
|
||||||
</module>
|
|
||||||
<module name="LocalVariableName">
|
|
||||||
<property name="tokens" value="VARIABLE_DEF"/>
|
|
||||||
<property name="format" value="^[a-z][a-zA-Z0-9]*$"/>
|
|
||||||
<property name="allowOneCharVarInForLoop" value="true"/>
|
|
||||||
<message key="name.invalidPattern"
|
|
||||||
value="Local variable name ''{0}'' must match pattern ''{1}''."/>
|
|
||||||
</module>
|
|
||||||
<module name="ClassTypeParameterName">
|
|
||||||
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
|
|
||||||
<message key="name.invalidPattern"
|
|
||||||
value="Class type name ''{0}'' must match pattern ''{1}''."/>
|
|
||||||
</module>
|
|
||||||
<module name="MethodTypeParameterName">
|
|
||||||
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
|
|
||||||
<message key="name.invalidPattern"
|
|
||||||
value="Method type name ''{0}'' must match pattern ''{1}''."/>
|
|
||||||
</module>
|
|
||||||
<module name="NoFinalizer"/>
|
|
||||||
<module name="AbbreviationAsWordInName">
|
|
||||||
<property name="ignoreFinal" value="false"/>
|
|
||||||
<property name="allowedAbbreviationLength" value="1"/>
|
|
||||||
</module>
|
|
||||||
<module name="DeclarationOrder"/>
|
|
||||||
<module name="OverloadMethodsDeclarationOrder"/>
|
|
||||||
<module name="VariableDeclarationUsageDistance"/>
|
|
||||||
<module name="MethodParamPad"/>
|
|
||||||
<module name="StringLiteralEquality"/>
|
|
||||||
<module name="BooleanExpressionComplexity">
|
|
||||||
<property name="max" value="5"/>
|
|
||||||
</module>
|
|
||||||
<module name="OperatorWrap">
|
|
||||||
<property name="option" value="NL"/>
|
|
||||||
<property name="tokens" value="BAND, BOR, BSR, BXOR, DIV, EQUAL, GE, GT, LAND, LE, LITERAL_INSTANCEOF, LOR, LT, MINUS, MOD, NOT_EQUAL, PLUS, QUESTION, SL, SR, STAR "/>
|
|
||||||
</module>
|
|
||||||
<module name="CyclomaticComplexity">
|
|
||||||
<property name="max" value="15"/>
|
|
||||||
</module>
|
|
||||||
<module name="JavaNCSS">
|
|
||||||
<property name="methodMaximum" value="40"/>
|
|
||||||
<property name="classMaximum" value="1000"/>
|
|
||||||
</module>
|
|
||||||
<module name="AnnotationLocation">
|
|
||||||
<property name="tokens" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF"/>
|
|
||||||
</module>
|
|
||||||
<module name="AnnotationLocation">
|
|
||||||
<property name="tokens" value="VARIABLE_DEF"/>
|
|
||||||
<property name="allowSamelineMultipleAnnotations" value="true"/>
|
|
||||||
</module>
|
|
||||||
<module name="NonEmptyAtclauseDescription"/>
|
|
||||||
<module name="JavadocTagContinuationIndentation">
|
|
||||||
<property name="offset" value="2"/>
|
|
||||||
</module>
|
|
||||||
<module name="AtclauseOrder">
|
|
||||||
<property name="tagOrder" value="@param, @return, @throws, @deprecated"/>
|
|
||||||
<property name="target" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF, VARIABLE_DEF"/>
|
|
||||||
</module>
|
|
||||||
<module name="JavadocMethod">
|
|
||||||
<property name="allowedAnnotations" value="Override, EventHandler"/>
|
|
||||||
<property name="tokens" value="METHOD_DEF, ANNOTATION_FIELD_DEF"/> <!-- exclude CTOR_DEF -->
|
|
||||||
</module>
|
|
||||||
<module name="MissingJavadocMethod">
|
|
||||||
<property name="scope" value="package"/>
|
|
||||||
<property name="minLineCount" value="4"/>
|
|
||||||
<property name="allowedAnnotations" value="Override, EventHandler"/>
|
|
||||||
<property name="tokens" value="METHOD_DEF, ANNOTATION_FIELD_DEF"/> <!-- exclude CTOR_DEF -->
|
|
||||||
</module>
|
|
||||||
<module name="MissingJavadocMethod">
|
|
||||||
<property name="scope" value="private"/>
|
|
||||||
<property name="minLineCount" value="16"/>
|
|
||||||
<property name="allowedAnnotations" value="Override, EventHandler"/>
|
|
||||||
<property name="tokens" value="METHOD_DEF, ANNOTATION_FIELD_DEF"/> <!-- exclude CTOR_DEF -->
|
|
||||||
</module>
|
|
||||||
<!-- TODO Checkstyle/#4089: need "allowedAnnotations" property to skip @Comment fields
|
|
||||||
<module name="JavadocVariable">
|
|
||||||
<property name="scope" value="package"/>
|
|
||||||
<property name="tokens" value="VARIABLE_DEF"/>
|
|
||||||
</module>
|
|
||||||
-->
|
|
||||||
<module name="MethodName">
|
|
||||||
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9_]*$"/>
|
|
||||||
<message key="name.invalidPattern"
|
|
||||||
value="Method name ''{0}'' must match pattern ''{1}''."/>
|
|
||||||
</module>
|
|
||||||
<module name="SingleLineJavadoc">
|
|
||||||
<property name="ignoredTags" value="@return"/>
|
|
||||||
</module>
|
|
||||||
<module name="EmptyCatchBlock">
|
|
||||||
<property name="exceptionVariableName" value="ignore|ignored"/>
|
|
||||||
</module>
|
|
||||||
<module name="MissingOverride"/>
|
|
||||||
<module name="EqualsHashCode"/>
|
|
||||||
<module name="EqualsAvoidNull"/>
|
|
||||||
<module name="Regexp">
|
|
||||||
<property name="format" value="\.to(Lower|Upper)Case\(\)"/>
|
|
||||||
<property name="illegalPattern" value="true"/>
|
|
||||||
<property name="ignoreComments" value="true"/>
|
|
||||||
<property name="message" value="Use toLowerCase/toUpperCase with Locale"/>
|
|
||||||
</module>
|
|
||||||
</module>
|
|
||||||
<module name="FileTabCharacter"/>
|
|
||||||
</module>
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
version: '2' # required to adjust maintainability checks
|
|
||||||
|
|
||||||
plugins:
|
|
||||||
checkstyle:
|
|
||||||
enabled: true
|
|
||||||
config:
|
|
||||||
file: '.checkstyle.xml'
|
|
||||||
|
|
||||||
checks:
|
|
||||||
# We disable all the following CodeClimate checks: Checkstyle already checks for these things and has the advantage
|
|
||||||
# that the Checkstyle config can also be used in one's IDE.
|
|
||||||
argument-count:
|
|
||||||
enabled: false
|
|
||||||
complex-logic:
|
|
||||||
enabled: false
|
|
||||||
file-lines:
|
|
||||||
enabled: false
|
|
||||||
method-complexity:
|
|
||||||
enabled: false
|
|
||||||
method-count:
|
|
||||||
enabled: false
|
|
||||||
method-lines:
|
|
||||||
enabled: false
|
|
||||||
nested-control-flow:
|
|
||||||
enabled: false
|
|
||||||
return-statements:
|
|
||||||
enabled: false
|
|
||||||
similar-code:
|
|
||||||
enabled: false
|
|
||||||
# The "identical-code" check would be cool to enable since Checkstyle offers no such functionality, but it is
|
|
||||||
# too aggressive and we'd have to suppress many reported warnings.
|
|
||||||
identical-code:
|
|
||||||
enabled: false
|
|
||||||
|
|
||||||
exclude_patterns:
|
|
||||||
# Exclude code from third-party sources
|
|
||||||
- 'src/main/java/fr/xephi/authme/mail/OAuth2Provider.java'
|
|
||||||
- 'src/main/java/fr/xephi/authme/mail/OAuth2SaslClient.java'
|
|
||||||
- 'src/main/java/fr/xephi/authme/mail/OAuth2SaslClientFactory.java'
|
|
||||||
- 'src/main/java/fr/xephi/authme/security/crypts/PhpBB.java'
|
|
||||||
- 'src/main/java/fr/xephi/authme/security/crypts/Whirlpool.java'
|
|
||||||
- 'src/main/java/fr/xephi/authme/security/crypts/Wordpress.java'
|
|
||||||
# Don't check test classes
|
|
||||||
- 'src/test/java/**/*Test.java'
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
# Top-most EditorConfig file
|
|
||||||
root = true
|
|
||||||
|
|
||||||
# Unix-style newlines with a newline ending every file
|
|
||||||
[*]
|
|
||||||
end_of_line = lf
|
|
||||||
insert_final_newline = true
|
|
||||||
|
|
||||||
# Set the charset, and space indention
|
|
||||||
[*.java]
|
|
||||||
charset = utf-8
|
|
||||||
indent_style = space
|
|
||||||
indent_size = 4
|
|
||||||
@@ -47,8 +47,10 @@ body:
|
|||||||
description: Which server implementation are you using?
|
description: Which server implementation are you using?
|
||||||
multiple: false
|
multiple: false
|
||||||
options:
|
options:
|
||||||
- Standalone server (no proxy)
|
- Standalone(Spigot)
|
||||||
|
- Standalone(Folia)
|
||||||
- BungeeCord
|
- BungeeCord
|
||||||
|
- Velocity
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
|
||||||
@@ -60,6 +62,9 @@ body:
|
|||||||
options:
|
options:
|
||||||
- SQLite
|
- SQLite
|
||||||
- MySQL
|
- MySQL
|
||||||
|
- H2
|
||||||
|
- MariaDB
|
||||||
|
- PostgreSQL
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
name: Feature request
|
name: Feature request
|
||||||
description: Suggest an idea for AuthMe
|
description: Suggest an idea for AuthMe
|
||||||
labels: 'Type: enhancement'
|
labels: 'enhancement'
|
||||||
|
|
||||||
body:
|
body:
|
||||||
- type: markdown
|
- type: markdown
|
||||||
|
|||||||
@@ -10,3 +10,7 @@ updates:
|
|||||||
- dependency-name: com.google.guava:guava
|
- dependency-name: com.google.guava:guava
|
||||||
- dependency-name: org.apache.logging.log4j:log4j-core
|
- dependency-name: org.apache.logging.log4j:log4j-core
|
||||||
- dependency-name: com.zaxxer:HikariCP
|
- dependency-name: com.zaxxer:HikariCP
|
||||||
|
- dependency-name: "org.mockito:mockito-core" # Mockito 5 requires Java 11
|
||||||
|
versions: ">= 5"
|
||||||
|
- dependency-name: "org.slf4j:slf4j-simple"
|
||||||
|
versions: ">= 1.7.36"
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
name: Plugin Build
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
push:
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
if: ${{ !contains(github.event.head_commit.message, '[skip]') }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout Repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup Java
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
java-version: 21
|
||||||
|
distribution: temurin
|
||||||
|
- name: Setup Gradle
|
||||||
|
uses: gradle/actions/setup-gradle@v4
|
||||||
|
- name: Make Gradle Wrapper Executable
|
||||||
|
run: chmod +x ./gradlew
|
||||||
|
- name: Build
|
||||||
|
run: ./gradlew clean build
|
||||||
|
- name: Capture Build Artifacts
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: Artifacts
|
||||||
|
path: outs/
|
||||||
|
runtime-test:
|
||||||
|
name: Plugin Runtime Test
|
||||||
|
needs: [ build ]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- mcVersion: '1.8.8'
|
||||||
|
javaVersion: '8'
|
||||||
|
- mcVersion: '1.12.2'
|
||||||
|
javaVersion: '8'
|
||||||
|
- mcVersion: '1.18.2'
|
||||||
|
javaVersion: '17'
|
||||||
|
- mcVersion: '1.20.4'
|
||||||
|
javaVersion: '21'
|
||||||
|
- mcVersion: '1.20.6'
|
||||||
|
javaVersion: '21'
|
||||||
|
steps:
|
||||||
|
- uses: HaHaWTH/minecraft-plugin-runtime-test@paper
|
||||||
|
with:
|
||||||
|
server-version: ${{ matrix.mcVersion }}
|
||||||
|
java-version: ${{ matrix.javaVersion }}
|
||||||
|
artifact-name: Artifacts
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
# This workflow will build a package using Maven and then publish it to GitHub packages when a release is created
|
|
||||||
# For more information see: https://github.com/actions/setup-java/blob/main/docs/advanced-usage.md#apache-maven-with-a-settings-path
|
|
||||||
|
|
||||||
name: Maven Package
|
|
||||||
|
|
||||||
on:
|
|
||||||
release:
|
|
||||||
types: [created]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
packages: write
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- name: Set up JDK 11
|
|
||||||
uses: actions/setup-java@v3
|
|
||||||
with:
|
|
||||||
java-version: '11'
|
|
||||||
distribution: 'temurin'
|
|
||||||
server-id: github # Value of the distributionManagement/repository/id field of the pom.xml
|
|
||||||
settings-path: ${{ github.workspace }} # location for the settings.xml file
|
|
||||||
|
|
||||||
- name: Build with Maven
|
|
||||||
run: mvn -B package --file pom.xml
|
|
||||||
|
|
||||||
- name: Publish to GitHub Packages Apache Maven
|
|
||||||
run: mvn deploy -s $GITHUB_WORKSPACE/settings.xml
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ github.token }}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
name: Java CI
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
Build:
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
jdkversion: [11]
|
|
||||||
runs-on: windows-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: actions/setup-java@v3
|
|
||||||
with:
|
|
||||||
distribution: 'temurin'
|
|
||||||
java-version: ${{ matrix.jdkversion }}
|
|
||||||
cache: 'maven'
|
|
||||||
- name: 使用Maven构建
|
|
||||||
run: mvn -V -B clean package --file pom.xml
|
|
||||||
|
|
||||||
+10
-109
@@ -1,115 +1,16 @@
|
|||||||
### Java files ###
|
# Mac filesystem dust
|
||||||
*.class
|
.DS_Store/
|
||||||
MANIFEST.MF
|
|
||||||
|
|
||||||
# Package Files
|
|
||||||
#*.jar
|
|
||||||
*.war
|
|
||||||
*.ear
|
|
||||||
|
|
||||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
|
||||||
hs_err_pid*
|
|
||||||
|
|
||||||
# Mac OS
|
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
### Intellij ###
|
# Linux temp files
|
||||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm
|
*~
|
||||||
# Ignore project files
|
|
||||||
*.iml
|
|
||||||
*.java___jb_tmp___
|
|
||||||
|
|
||||||
# Ignore IDEA directory
|
|
||||||
.idea/*
|
|
||||||
|
|
||||||
# Include the project's code style settings file
|
|
||||||
!.idea/codeStyleSettings.xml
|
|
||||||
/target/class/
|
|
||||||
# File-based project format:
|
|
||||||
*.ipr
|
|
||||||
*.iws
|
|
||||||
|
|
||||||
### Plugin-specific files: ###
|
|
||||||
# IntelliJ
|
# IntelliJ
|
||||||
/out/
|
*.iml
|
||||||
|
.idea
|
||||||
|
|
||||||
# mpeltonen/sbt-idea plugin
|
# Gradle
|
||||||
.idea_modules/
|
!gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
# JIRA plugin
|
|
||||||
atlassian-ide-plugin.xml
|
|
||||||
|
|
||||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
|
||||||
com_crashlytics_export_strings.xml
|
|
||||||
crashlytics.properties
|
|
||||||
crashlytics-build.properties
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Eclipse ###
|
|
||||||
*.pydevproject
|
|
||||||
.metadata
|
|
||||||
.gradle
|
.gradle
|
||||||
bin/
|
build
|
||||||
tmp/
|
outs
|
||||||
*.tmp
|
|
||||||
*.bak
|
|
||||||
*.swp
|
|
||||||
*~.nib
|
|
||||||
local.properties
|
|
||||||
.settings/
|
|
||||||
.loadpath
|
|
||||||
|
|
||||||
# Eclipse Core
|
|
||||||
.project
|
|
||||||
|
|
||||||
# External tool builders
|
|
||||||
.externalToolBuilders/
|
|
||||||
|
|
||||||
# Locally stored "Eclipse launch configurations"
|
|
||||||
*.launch
|
|
||||||
|
|
||||||
# CDT-specific
|
|
||||||
.cproject
|
|
||||||
|
|
||||||
# JDT-specific (Eclipse Java Development Tools)
|
|
||||||
.classpath
|
|
||||||
|
|
||||||
# PDT-specific
|
|
||||||
.buildpath
|
|
||||||
|
|
||||||
# sbteclipse plugin
|
|
||||||
.target
|
|
||||||
|
|
||||||
# TeXlipse plugin
|
|
||||||
.texlipse
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Maven ###
|
|
||||||
target/
|
|
||||||
pom.xml.tag
|
|
||||||
pom.xml.releaseBackup
|
|
||||||
pom.xml.versionsBackup
|
|
||||||
pom.xml.next
|
|
||||||
release.properties
|
|
||||||
dependency-reduced-pom.xml
|
|
||||||
buildNumber.properties
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### NetBeans ###
|
|
||||||
nbproject/private/
|
|
||||||
build/
|
|
||||||
nbbuild/
|
|
||||||
dist/
|
|
||||||
nbdist/
|
|
||||||
nbactions.xml
|
|
||||||
nb-configuration.xml
|
|
||||||
.nb-gradle/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Git ###
|
|
||||||
# Don't exclude the .gitignore itself
|
|
||||||
!.gitignore
|
|
||||||
|
|||||||
Generated
-291
@@ -1,291 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="ProjectCodeStyleSettingsManager">
|
|
||||||
<option name="PER_PROJECT_SETTINGS">
|
|
||||||
<value>
|
|
||||||
<option name="AUTODETECT_INDENTS" value="false" />
|
|
||||||
<option name="LINE_SEPARATOR" value=" " />
|
|
||||||
<option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="99" />
|
|
||||||
<option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="99" />
|
|
||||||
<option name="JD_ADD_BLANK_AFTER_PARM_COMMENTS" value="true" />
|
|
||||||
<option name="JD_ADD_BLANK_AFTER_RETURN" value="true" />
|
|
||||||
<XML>
|
|
||||||
<option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" />
|
|
||||||
</XML>
|
|
||||||
<codeStyleSettings language="JAVA">
|
|
||||||
<arrangement>
|
|
||||||
<rules>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<FIELD>true</FIELD>
|
|
||||||
<FINAL>true</FINAL>
|
|
||||||
<PUBLIC>true</PUBLIC>
|
|
||||||
<STATIC>true</STATIC>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<FIELD>true</FIELD>
|
|
||||||
<FINAL>true</FINAL>
|
|
||||||
<PROTECTED>true</PROTECTED>
|
|
||||||
<STATIC>true</STATIC>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<FIELD>true</FIELD>
|
|
||||||
<FINAL>true</FINAL>
|
|
||||||
<PACKAGE_PRIVATE>true</PACKAGE_PRIVATE>
|
|
||||||
<STATIC>true</STATIC>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<FIELD>true</FIELD>
|
|
||||||
<FINAL>true</FINAL>
|
|
||||||
<PRIVATE>true</PRIVATE>
|
|
||||||
<STATIC>true</STATIC>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<FIELD>true</FIELD>
|
|
||||||
<PUBLIC>true</PUBLIC>
|
|
||||||
<STATIC>true</STATIC>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<FIELD>true</FIELD>
|
|
||||||
<PROTECTED>true</PROTECTED>
|
|
||||||
<STATIC>true</STATIC>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<FIELD>true</FIELD>
|
|
||||||
<PACKAGE_PRIVATE>true</PACKAGE_PRIVATE>
|
|
||||||
<STATIC>true</STATIC>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<FIELD>true</FIELD>
|
|
||||||
<PRIVATE>true</PRIVATE>
|
|
||||||
<STATIC>true</STATIC>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<INITIALIZER_BLOCK>true</INITIALIZER_BLOCK>
|
|
||||||
<STATIC>true</STATIC>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<FIELD>true</FIELD>
|
|
||||||
<FINAL>true</FINAL>
|
|
||||||
<PUBLIC>true</PUBLIC>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<FIELD>true</FIELD>
|
|
||||||
<FINAL>true</FINAL>
|
|
||||||
<PROTECTED>true</PROTECTED>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<FIELD>true</FIELD>
|
|
||||||
<FINAL>true</FINAL>
|
|
||||||
<PACKAGE_PRIVATE>true</PACKAGE_PRIVATE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<FIELD>true</FIELD>
|
|
||||||
<FINAL>true</FINAL>
|
|
||||||
<PRIVATE>true</PRIVATE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<FIELD>true</FIELD>
|
|
||||||
<PUBLIC>true</PUBLIC>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<FIELD>true</FIELD>
|
|
||||||
<PROTECTED>true</PROTECTED>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<FIELD>true</FIELD>
|
|
||||||
<PACKAGE_PRIVATE>true</PACKAGE_PRIVATE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<FIELD>true</FIELD>
|
|
||||||
<PRIVATE>true</PRIVATE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<FIELD>true</FIELD>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<INITIALIZER_BLOCK>true</INITIALIZER_BLOCK>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<CONSTRUCTOR>true</CONSTRUCTOR>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<METHOD>true</METHOD>
|
|
||||||
<STATIC>true</STATIC>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<METHOD>true</METHOD>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<METHOD>true</METHOD>
|
|
||||||
<PRIVATE>true</PRIVATE>
|
|
||||||
<STATIC>true</STATIC>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<ENUM>true</ENUM>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<INTERFACE>true</INTERFACE>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<CLASS>true</CLASS>
|
|
||||||
<STATIC>true</STATIC>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<CLASS>true</CLASS>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
</rules>
|
|
||||||
</arrangement>
|
|
||||||
</codeStyleSettings>
|
|
||||||
</value>
|
|
||||||
</option>
|
|
||||||
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
-35
@@ -1,35 +0,0 @@
|
|||||||
dist: focal
|
|
||||||
|
|
||||||
language: java
|
|
||||||
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
- env:
|
|
||||||
- JDK_VERSION=8
|
|
||||||
- env:
|
|
||||||
- JDK_VERSION=11
|
|
||||||
- env:
|
|
||||||
- JDK_VERSION=17
|
|
||||||
|
|
||||||
before_install:
|
|
||||||
- "[[ -d $HOME/.sdkman/ ]] && [[ -d $HOME/.sdkman/bin/ ]] || rm -rf $HOME/.sdkman/"
|
|
||||||
- curl -s "https://get.sdkman.io" | bash
|
|
||||||
- mkdir -p "$HOME/.sdkman/etc/"
|
|
||||||
- echo sdkman_auto_answer=true > "$HOME/.sdkman/etc/config"
|
|
||||||
- echo sdkman_auto_selfupdate=true >> "$HOME/.sdkman/etc/config"
|
|
||||||
- source "$HOME/.sdkman/bin/sdkman-init.sh"
|
|
||||||
|
|
||||||
install:
|
|
||||||
- sdk install java $(sdk list java | grep -o "$JDK_VERSION\.[0-9]*\.[0-9]*\-open" | head -1)
|
|
||||||
- sdk install maven
|
|
||||||
- export JAVA_HOME="$HOME/.sdkman/candidates/java/current"
|
|
||||||
- export PATH=${JAVA_HOME}/bin:${PATH}
|
|
||||||
- export MAVEN_HOME="$HOME/.sdkman/candidates/maven/current"
|
|
||||||
- export M2_HOME="$MAVEN_HOME"
|
|
||||||
- export PATH=${M2_HOME}/bin:${PATH}
|
|
||||||
- env
|
|
||||||
- mvn -v
|
|
||||||
|
|
||||||
cache:
|
|
||||||
directories:
|
|
||||||
- $HOME/.m2/repository
|
|
||||||
@@ -1,23 +1,21 @@
|
|||||||
GNU GENERAL PUBLIC LICENSE
|
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||||
Version 3, 29 June 2007
|
Version 3, 19 November 2007
|
||||||
|
|
||||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
of this license document, but changing it is not allowed.
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
Preamble
|
Preamble
|
||||||
|
|
||||||
The GNU General Public License is a free, copyleft license for
|
The GNU Affero General Public License is a free, copyleft license for
|
||||||
software and other kinds of works.
|
software and other kinds of works, specifically designed to ensure
|
||||||
|
cooperation with the community in the case of network server software.
|
||||||
|
|
||||||
The licenses for most software and other practical works are designed
|
The licenses for most software and other practical works are designed
|
||||||
to take away your freedom to share and change the works. By contrast,
|
to take away your freedom to share and change the works. By contrast,
|
||||||
the GNU General Public License is intended to guarantee your freedom to
|
our General Public Licenses are intended to guarantee your freedom to
|
||||||
share and change all versions of a program--to make sure it remains free
|
share and change all versions of a program--to make sure it remains free
|
||||||
software for all its users. We, the Free Software Foundation, use the
|
software for all its users.
|
||||||
GNU General Public License for most of our software; it applies also to
|
|
||||||
any other work released this way by its authors. You can apply it to
|
|
||||||
your programs, too.
|
|
||||||
|
|
||||||
When we speak of free software, we are referring to freedom, not
|
When we speak of free software, we are referring to freedom, not
|
||||||
price. Our General Public Licenses are designed to make sure that you
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
@@ -26,44 +24,34 @@ them if you wish), that you receive source code or can get it if you
|
|||||||
want it, that you can change the software or use pieces of it in new
|
want it, that you can change the software or use pieces of it in new
|
||||||
free programs, and that you know you can do these things.
|
free programs, and that you know you can do these things.
|
||||||
|
|
||||||
To protect your rights, we need to prevent others from denying you
|
Developers that use our General Public Licenses protect your rights
|
||||||
these rights or asking you to surrender the rights. Therefore, you have
|
with two steps: (1) assert copyright on the software, and (2) offer
|
||||||
certain responsibilities if you distribute copies of the software, or if
|
you this License which gives you legal permission to copy, distribute
|
||||||
you modify it: responsibilities to respect the freedom of others.
|
and/or modify the software.
|
||||||
|
|
||||||
For example, if you distribute copies of such a program, whether
|
A secondary benefit of defending all users' freedom is that
|
||||||
gratis or for a fee, you must pass on to the recipients the same
|
improvements made in alternate versions of the program, if they
|
||||||
freedoms that you received. You must make sure that they, too, receive
|
receive widespread use, become available for other developers to
|
||||||
or can get the source code. And you must show them these terms so they
|
incorporate. Many developers of free software are heartened and
|
||||||
know their rights.
|
encouraged by the resulting cooperation. However, in the case of
|
||||||
|
software used on network servers, this result may fail to come about.
|
||||||
|
The GNU General Public License permits making a modified version and
|
||||||
|
letting the public access it on a server without ever releasing its
|
||||||
|
source code to the public.
|
||||||
|
|
||||||
Developers that use the GNU GPL protect your rights with two steps:
|
The GNU Affero General Public License is designed specifically to
|
||||||
(1) assert copyright on the software, and (2) offer you this License
|
ensure that, in such cases, the modified source code becomes available
|
||||||
giving you legal permission to copy, distribute and/or modify it.
|
to the community. It requires the operator of a network server to
|
||||||
|
provide the source code of the modified version running there to the
|
||||||
|
users of that server. Therefore, public use of a modified version, on
|
||||||
|
a publicly accessible server, gives the public access to the source
|
||||||
|
code of the modified version.
|
||||||
|
|
||||||
For the developers' and authors' protection, the GPL clearly explains
|
An older license, called the Affero General Public License and
|
||||||
that there is no warranty for this free software. For both users' and
|
published by Affero, was designed to accomplish similar goals. This is
|
||||||
authors' sake, the GPL requires that modified versions be marked as
|
a different license, not a version of the Affero GPL, but Affero has
|
||||||
changed, so that their problems will not be attributed erroneously to
|
released a new version of the Affero GPL which permits relicensing under
|
||||||
authors of previous versions.
|
this license.
|
||||||
|
|
||||||
Some devices are designed to deny users access to install or run
|
|
||||||
modified versions of the software inside them, although the manufacturer
|
|
||||||
can do so. This is fundamentally incompatible with the aim of
|
|
||||||
protecting users' freedom to change the software. The systematic
|
|
||||||
pattern of such abuse occurs in the area of products for individuals to
|
|
||||||
use, which is precisely where it is most unacceptable. Therefore, we
|
|
||||||
have designed this version of the GPL to prohibit the practice for those
|
|
||||||
products. If such problems arise substantially in other domains, we
|
|
||||||
stand ready to extend this provision to those domains in future versions
|
|
||||||
of the GPL, as needed to protect the freedom of users.
|
|
||||||
|
|
||||||
Finally, every program is threatened constantly by software patents.
|
|
||||||
States should not allow patents to restrict development and use of
|
|
||||||
software on general-purpose computers, but in those that do, we wish to
|
|
||||||
avoid the special danger that patents applied to a free program could
|
|
||||||
make it effectively proprietary. To prevent this, the GPL assures that
|
|
||||||
patents cannot be used to render the program non-free.
|
|
||||||
|
|
||||||
The precise terms and conditions for copying, distribution and
|
The precise terms and conditions for copying, distribution and
|
||||||
modification follow.
|
modification follow.
|
||||||
@@ -72,7 +60,7 @@ modification follow.
|
|||||||
|
|
||||||
0. Definitions.
|
0. Definitions.
|
||||||
|
|
||||||
"This License" refers to version 3 of the GNU General Public License.
|
"This License" refers to version 3 of the GNU Affero General Public License.
|
||||||
|
|
||||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
works, such as semiconductor masks.
|
works, such as semiconductor masks.
|
||||||
@@ -549,35 +537,45 @@ to collect a royalty for further conveying from those to whom you convey
|
|||||||
the Program, the only way you could satisfy both those terms and this
|
the Program, the only way you could satisfy both those terms and this
|
||||||
License would be to refrain entirely from conveying the Program.
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
13. Use with the GNU Affero General Public License.
|
13. Remote Network Interaction; Use with the GNU General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, if you modify the
|
||||||
|
Program, your modified version must prominently offer all users
|
||||||
|
interacting with it remotely through a computer network (if your version
|
||||||
|
supports such interaction) an opportunity to receive the Corresponding
|
||||||
|
Source of your version by providing access to the Corresponding Source
|
||||||
|
from a network server at no charge, through some standard or customary
|
||||||
|
means of facilitating copying of software. This Corresponding Source
|
||||||
|
shall include the Corresponding Source for any work covered by version 3
|
||||||
|
of the GNU General Public License that is incorporated pursuant to the
|
||||||
|
following paragraph.
|
||||||
|
|
||||||
Notwithstanding any other provision of this License, you have
|
Notwithstanding any other provision of this License, you have
|
||||||
permission to link or combine any covered work with a work licensed
|
permission to link or combine any covered work with a work licensed
|
||||||
under version 3 of the GNU Affero General Public License into a single
|
under version 3 of the GNU General Public License into a single
|
||||||
combined work, and to convey the resulting work. The terms of this
|
combined work, and to convey the resulting work. The terms of this
|
||||||
License will continue to apply to the part which is the covered work,
|
License will continue to apply to the part which is the covered work,
|
||||||
but the special requirements of the GNU Affero General Public License,
|
but the work with which it is combined will remain governed by version
|
||||||
section 13, concerning interaction through a network will apply to the
|
3 of the GNU General Public License.
|
||||||
combination as such.
|
|
||||||
|
|
||||||
14. Revised Versions of this License.
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
The Free Software Foundation may publish revised and/or new versions of
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
the GNU General Public License from time to time. Such new versions will
|
the GNU Affero General Public License from time to time. Such new versions
|
||||||
be similar in spirit to the present version, but may differ in detail to
|
will be similar in spirit to the present version, but may differ in detail to
|
||||||
address new problems or concerns.
|
address new problems or concerns.
|
||||||
|
|
||||||
Each version is given a distinguishing version number. If the
|
Each version is given a distinguishing version number. If the
|
||||||
Program specifies that a certain numbered version of the GNU General
|
Program specifies that a certain numbered version of the GNU Affero General
|
||||||
Public License "or any later version" applies to it, you have the
|
Public License "or any later version" applies to it, you have the
|
||||||
option of following the terms and conditions either of that numbered
|
option of following the terms and conditions either of that numbered
|
||||||
version or of any later version published by the Free Software
|
version or of any later version published by the Free Software
|
||||||
Foundation. If the Program does not specify a version number of the
|
Foundation. If the Program does not specify a version number of the
|
||||||
GNU General Public License, you may choose any version ever published
|
GNU Affero General Public License, you may choose any version ever published
|
||||||
by the Free Software Foundation.
|
by the Free Software Foundation.
|
||||||
|
|
||||||
If the Program specifies that a proxy can decide which future
|
If the Program specifies that a proxy can decide which future
|
||||||
versions of the GNU General Public License can be used, that proxy's
|
versions of the GNU Affero General Public License can be used, that proxy's
|
||||||
public statement of acceptance of a version permanently authorizes you
|
public statement of acceptance of a version permanently authorizes you
|
||||||
to choose that version for the Program.
|
to choose that version for the Program.
|
||||||
|
|
||||||
@@ -631,44 +629,33 @@ to attach them to the start of each source file to most effectively
|
|||||||
state the exclusion of warranty; and each file should have at least
|
state the exclusion of warranty; and each file should have at least
|
||||||
the "copyright" line and a pointer to where the full notice is found.
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
{one line to give the program's name and a brief idea of what it does.}
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
Copyright (C) {year} {name of author}
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
This program is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU Affero General Public License as published
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
by the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU Affero General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
Also add information on how to contact you by electronic and paper mail.
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
If the program does terminal interaction, make it output a short
|
If your software can interact with users remotely through a computer
|
||||||
notice like this when it starts in an interactive mode:
|
network, you should also make sure that it provides a way for users to
|
||||||
|
get its source. For example, if your program is a web application, its
|
||||||
{project} Copyright (C) {year} {fullname}
|
interface could display a "Source" link that leads users to an archive
|
||||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
of the code. There are many ways you could offer source, and different
|
||||||
This is free software, and you are welcome to redistribute it
|
solutions will be better for different programs; see section 13 for the
|
||||||
under certain conditions; type `show c' for details.
|
specific requirements.
|
||||||
|
|
||||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
|
||||||
parts of the General Public License. Of course, your program's commands
|
|
||||||
might be different; for a GUI interface, you would use an "about box".
|
|
||||||
|
|
||||||
You should also get your employer (if you work as a programmer) or school,
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
For more information on this, and how to apply and follow the GNU GPL, see
|
For more information on this, and how to apply and follow the GNU AGPL, see
|
||||||
<http://www.gnu.org/licenses/>.
|
<https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
The GNU General Public License does not permit incorporating your program
|
|
||||||
into proprietary programs. If your program is a subroutine library, you
|
|
||||||
may consider it more useful to permit linking proprietary applications with
|
|
||||||
the library. If this is what you want to do, use the GNU Lesser General
|
|
||||||
Public License instead of this License. But first, please read
|
|
||||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
# AuthMeReReloaded
|
||||||
|
**"Bukkit 的最佳身份验证插件的分支!"**
|
||||||
|
|
||||||
|

|
||||||
|
<p align="center">
|
||||||
|
<img src="https://img.shields.io/github/languages/code-size/HaHaWTH/AuthMeReReloaded.svg" alt="Code size"/>
|
||||||
|
<img src="https://img.shields.io/github/repo-size/HaHaWTH/AuthMeReReloaded.svg" alt="GitHub repo size"/>
|
||||||
|
<img src="https://www.codefactor.io/repository/github/hahawth/authmerereloaded/badge" alt="CodeFactor" />
|
||||||
|
<img src="https://img.shields.io/github/downloads/HaHaWTH/AuthMeReReloaded/total" alt="Downloads" />
|
||||||
|
</p>
|
||||||
|
|
||||||
|
**详细改动:**
|
||||||
|
1. 改进邮件发送逻辑,支持更多邮件
|
||||||
|
2. 关闭邮件发送(当服务器关闭时,向您发送邮件)
|
||||||
|
3. 原有漏洞修复
|
||||||
|
4. 反幽灵玩家(重复登录错误)
|
||||||
|
5. 按服务器分支使用最佳性能方法
|
||||||
|
6. 基岩兼容性(需要Floodgate)(基于 UUID)
|
||||||
|
7. 更新检查器
|
||||||
|
8. 集成 GUI 验证码功能(需要 Bedrock 兼容性和 ProtocolLib)(70% 异步)
|
||||||
|
9. 改进监听器
|
||||||
|
10. 改进玩家登录逻辑以减少延迟
|
||||||
|
11. 自动清除机器人数据
|
||||||
|
12. 支持**Folia(正在测试中)**
|
||||||
|
13. F键菜单兼容
|
||||||
|
14. 自动修复传送卡传送门/地底问题
|
||||||
|
15. **Velocity支持 (详见 [Velocity Support](./vc-support.md))**
|
||||||
|
16. 基岩版玩家自动登录(可配置)
|
||||||
|
17. 修复旧版本(MC 1.13-)中的 "潜影盒 "崩溃问题
|
||||||
|
18. 支持 **H2 数据库**
|
||||||
|
19. 虚拟线程支持
|
||||||
|
20. **100% 兼容原版 authme 和扩展**
|
||||||
|
21. 更多......
|
||||||
|
|
||||||
|
**下载链接:**
|
||||||
|
[Release](https://github.com/HaHaWTH/AuthMeReReloaded/releases/latest)
|
||||||
|
[Actions(开发版,使用风险自负!)](https://github.com/HaHaWTH/AuthMeReReloaded/actions/workflows/maven.yml)
|
||||||
|
|
||||||
|
如果您的服务器使用 FRP(内网穿透),此插件可能会有所帮助 [HAProxy-Detector](https://github.com/HaHaWTH/HAProxy-Detector)
|
||||||
|
|
||||||
|
**欢迎提出请求和建议!**
|
||||||
|
|
||||||
|
<picture>
|
||||||
|
<source
|
||||||
|
media="(prefers-color-scheme: dark)"
|
||||||
|
srcset="
|
||||||
|
https://api.star-history.com/svg?repos=HaHaWTH/AuthMeReReloaded&type=Date&theme=dark
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=HaHaWTH/AuthMeReReloaded&type=Date" />
|
||||||
|
</picture>
|
||||||
@@ -1,4 +1,77 @@
|
|||||||
# AuthMeReReloaded
|
# AuthMeReReloaded
|
||||||
**"A fork of the best authentication plugin for the Bukkit modding API!"**
|
**"A fork of the best authentication plugin for the Bukkit modding API!⭐"**
|
||||||
|
|
||||||
|
[English](https://github.com/HaHaWTH/AuthMeReReloaded) | [简体中文](https://github.com/HaHaWTH/AuthMeReReloaded/blob/master/README-zh.md)
|
||||||
|
|
||||||

|

|
||||||
|
<p align="center">
|
||||||
|
<img src="https://img.shields.io/github/languages/code-size/HaHaWTH/AuthMeReReloaded.svg" alt="Code size"/>
|
||||||
|
<img src="https://img.shields.io/github/repo-size/HaHaWTH/AuthMeReReloaded.svg" alt="GitHub repo size"/>
|
||||||
|
<img src="https://www.codefactor.io/repository/github/hahawth/authmerereloaded/badge" alt="CodeFactor" />
|
||||||
|
<img alt="GitHub Downloads (all assets, all releases)" src="https://img.shields.io/github/downloads/HaHaWTH/AuthMeReReloaded/total?logo=github&label=GitHub%20Downloads&color=black">
|
||||||
|
<img alt="Spiget Downloads" src="https://img.shields.io/spiget/downloads/114010?logo=spigotmc&label=SpigotMC%20Downloads&color=orange">
|
||||||
|
<img alt="Modrinth Downloads" src="https://img.shields.io/modrinth/dt/3IEZ9vol?logo=modrinth&label=Modrinth%20Downloads&color=light-green">
|
||||||
|
<img alt="Hangar Downloads" src="https://img.shields.io/hangar/dt/AuthMeReReloaded?logo=hangar&label=Hangar%20Downloads&color=white">
|
||||||
|
</p>
|
||||||
|
|
||||||
|
**Detailed Changes:**
|
||||||
|
1. Improved mail sending logic & support more emails
|
||||||
|
2. Shutdown mail sending(When server is closed, email you)
|
||||||
|
3. Legacy bug fixes
|
||||||
|
4. Anti Ghost Player(Doubled login bug)
|
||||||
|
5. Use the best performance method by server brand
|
||||||
|
6. Bedrock Compatibility(Floodgate needed)(based on UUID)
|
||||||
|
7. Update checker
|
||||||
|
8. Integrated GUI Captcha feature(Bedrock compatibility & ProtocolLib needed)(70% Asynchronous)
|
||||||
|
9. Improved listeners
|
||||||
|
10. Player login logic improvement to reduce lag
|
||||||
|
11. Automatically purge bot data
|
||||||
|
12. **Folia support (in active testing)**
|
||||||
|
13. **Velocity support (See [Velocity Support](./vc-support.md))**
|
||||||
|
14. Support Virtual Threads caching
|
||||||
|
15. Automatically fix portal stuck issue
|
||||||
|
16. Automatically login for Bedrock players(configurable)
|
||||||
|
17. Fix shulker box crash bug on legacy versions(MC 1.13-)
|
||||||
|
18. **H2 database support**
|
||||||
|
19. **100% compatibility with original authme and extensions**
|
||||||
|
20. More......
|
||||||
|
|
||||||
|
**Download links:**
|
||||||
|
[Releases](https://github.com/HaHaWTH/AuthMeReReloaded/releases/latest)
|
||||||
|
[Actions(Dev builds, use at your own risk!)](https://github.com/HaHaWTH/AuthMeReReloaded/actions/workflows/maven.yml)
|
||||||
|
|
||||||
|
**Pull Requests and suggestions are welcome!**
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
* [Gradle](https://gradle.org/) - Dependency Management
|
||||||
|
|
||||||
|
The GradleWrapper in included in this project.
|
||||||
|
|
||||||
|
**Windows:**
|
||||||
|
|
||||||
|
```
|
||||||
|
gradlew.bat clean build
|
||||||
|
```
|
||||||
|
|
||||||
|
**macOS/Linux:**
|
||||||
|
|
||||||
|
```
|
||||||
|
./gradlew clean build
|
||||||
|
```
|
||||||
|
|
||||||
|
Build artifacts should be found in `./outs` folder.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Only modifications to AuthMeReloaded is under AGPL-3.0 license, AuthMeReloaded is licensed under GPL-3.0.
|
||||||
|
|
||||||
|
<picture>
|
||||||
|
<source
|
||||||
|
media="(prefers-color-scheme: dark)"
|
||||||
|
srcset="
|
||||||
|
https://api.star-history.com/svg?repos=HaHaWTH/AuthMeReReloaded&type=Date&theme=dark
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=HaHaWTH/AuthMeReReloaded&type=Date" />
|
||||||
|
</picture>
|
||||||
|
|||||||
@@ -0,0 +1,190 @@
|
|||||||
|
plugins {
|
||||||
|
`java-library`
|
||||||
|
`maven-publish`
|
||||||
|
id("com.gradleup.shadow") version "9.0.0-beta4"
|
||||||
|
}
|
||||||
|
|
||||||
|
description = "Fork of the first authentication plugin for the Bukkit API!"
|
||||||
|
|
||||||
|
java {
|
||||||
|
withSourcesJar()
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType<JavaCompile> {
|
||||||
|
options.encoding = "UTF-8"
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
mavenLocal()
|
||||||
|
// PaperMC
|
||||||
|
maven("https://papermc.io/repo/repository/maven-public/")
|
||||||
|
maven("https://repo.opencollab.dev/main/")
|
||||||
|
maven("https://repo.opencollab.dev/maven-snapshots/")
|
||||||
|
maven("https://s01.oss.sonatype.org/content/repositories/snapshots/")
|
||||||
|
maven("https://repository.apache.org/content/repositories/snapshots/")
|
||||||
|
maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots")
|
||||||
|
maven("https://repo.codemc.io/repository/maven-public/")
|
||||||
|
maven("https://repo.essentialsx.net/releases/")
|
||||||
|
maven("https://repo.dmulloy2.net/nexus/repository/releases/")
|
||||||
|
maven("https://repo.dmulloy2.net/nexus/repository/snapshots/")
|
||||||
|
maven("https://repo.onarandombox.com/multiverse-releases")
|
||||||
|
maven("https://jitpack.io/")
|
||||||
|
maven("https://repo.extendedclip.com/content/repositories/placeholderapi/")
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
// Spigot API, https://www.spigotmc.org/
|
||||||
|
compileOnly("org.spigotmc:spigot-api:1.20.6-R0.1-SNAPSHOT")
|
||||||
|
// Adventure API
|
||||||
|
implementation(libs.adventure.text.minimessage)
|
||||||
|
implementation(libs.adventure.platform.bukkit)
|
||||||
|
implementation(libs.adventure.text.serializer.gson)
|
||||||
|
// Java Libraries
|
||||||
|
compileOnly("org.geysermc.floodgate:api:2.2.2-SNAPSHOT")
|
||||||
|
// Jalu Injector
|
||||||
|
implementation(libs.injector)
|
||||||
|
// String comparison library. Used for dynamic help system.
|
||||||
|
implementation(libs.string.similarity)
|
||||||
|
// MaxMind GEO IP with our modifications to use GSON in replacement of the big Jackson dependency
|
||||||
|
// GSON is already included and therefore it reduces the file size in comparison to the original version
|
||||||
|
implementation(libs.maxmind.db.gson) {
|
||||||
|
exclude("com.google.code.gson", "gson")
|
||||||
|
}
|
||||||
|
// Library for tar archives
|
||||||
|
implementation(libs.javatar)
|
||||||
|
// Java Email Library
|
||||||
|
implementation(libs.commons.email)
|
||||||
|
// Log4J Logger (required by the console filter)
|
||||||
|
compileOnly(libs.log4j.core) // Log4J version bundled in 1.12.2
|
||||||
|
// Libby
|
||||||
|
implementation(libs.libby.bukkit)
|
||||||
|
// Database Connection Pool
|
||||||
|
implementation(libs.hikaricp) {
|
||||||
|
exclude("org.slf4j", "slf4j-api")
|
||||||
|
}
|
||||||
|
// HikariCP Logger
|
||||||
|
implementation(libs.slf4j.simple) // We can't update to 2.x as long as we use HikariCP for java 8
|
||||||
|
// PBKDF2 implementation
|
||||||
|
implementation(libs.pbkdf2)
|
||||||
|
// MySQL connector, shaded into the legacy jar
|
||||||
|
implementation(libs.mysql.connector.j)
|
||||||
|
implementation(libs.mariadb.java.client)
|
||||||
|
// Argon2 implementation
|
||||||
|
implementation(libs.argon2.jvm.nolibs)
|
||||||
|
// TOTP client
|
||||||
|
implementation(libs.googleauth)
|
||||||
|
// Keep in sync with spigot 1.19
|
||||||
|
implementation(libs.guava) {
|
||||||
|
exclude("org.checkerframework", "checker-qual")
|
||||||
|
}
|
||||||
|
implementation(libs.gson)
|
||||||
|
// ConfigMe
|
||||||
|
implementation(libs.configme) {
|
||||||
|
exclude("org.yaml", "snakeyaml")
|
||||||
|
}
|
||||||
|
// bStats metrics
|
||||||
|
implementation("org.bstats:bstats-bukkit:3.0.2")
|
||||||
|
// ProtocolLib
|
||||||
|
compileOnly("com.comphenix.protocol:ProtocolLib:5.3.0")
|
||||||
|
// LuckPerms plugin
|
||||||
|
compileOnly("net.luckperms:api:5.4")
|
||||||
|
// PermissionsEx plugin
|
||||||
|
compileOnly("ru.tehkode:PermissionsEx:1.23.5-SNAPSHOT")
|
||||||
|
// zPermissions plugin
|
||||||
|
compileOnly("org.tyrannyofheaven.bukkit:zPermissions:1.4.3-SNAPSHOT") {
|
||||||
|
exclude("org.avaje", "ebean")
|
||||||
|
}
|
||||||
|
// Vault, https://dev.bukkit.org/bukkit-plugins/vault/
|
||||||
|
compileOnly("net.milkbowl.vault:VaultAPI:1.7")
|
||||||
|
// Multi World plugin, https://www.spigotmc.org/resources/multiverse-core.390/
|
||||||
|
compileOnly("com.onarandombox.multiversecore:multiverse-core:4.3.14")
|
||||||
|
// EssentialsX plugin
|
||||||
|
compileOnly("net.essentialsx:EssentialsX:2.20.1") {
|
||||||
|
exclude("io.papermc", "paperlib")
|
||||||
|
}
|
||||||
|
// BCrypt implementation
|
||||||
|
implementation(libs.bcrypt)
|
||||||
|
// PlaceholderAPI
|
||||||
|
compileOnly("me.clip:placeholderapi:2.11.6")
|
||||||
|
// XAuth, another authentication plugin, required by the database converter
|
||||||
|
compileOnly("de.luricos.bukkit:xAuth:2.6.1-SNAPSHOT")
|
||||||
|
implementation(libs.datasourcecolumns)
|
||||||
|
implementation(libs.postgresql) {
|
||||||
|
exclude("org.checkerframework", "checker-qual")
|
||||||
|
}
|
||||||
|
// Required to mock the LuckPerms API
|
||||||
|
testImplementation(libs.checker.qual)
|
||||||
|
// Universal Scheduler
|
||||||
|
implementation(libs.universalscheduler)
|
||||||
|
// JDBC drivers for datasource integration tests
|
||||||
|
testImplementation(libs.sqlite.jdbc)
|
||||||
|
compileOnly(libs.h2)
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks {
|
||||||
|
processResources {
|
||||||
|
filesMatching("**/*.yml") {
|
||||||
|
expand(project.properties)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
build { dependsOn(shadowJar) }
|
||||||
|
|
||||||
|
// ShadowJar Config
|
||||||
|
shadowJar {
|
||||||
|
// Options
|
||||||
|
archiveFileName = "AuthMe-${project.version}.${archiveExtension.get()}"
|
||||||
|
destinationDirectory.set(file("$rootDir/outs"))
|
||||||
|
// Libraries Relocate
|
||||||
|
relocate("org.apache.http", "fr.xephi.authme.libs.org.apache.http")
|
||||||
|
relocate("org.apache.commons", "fr.xephi.authme.libs.org.apache.commons")
|
||||||
|
relocate("waffle", "fr.xephi.authme.libs.waffle")
|
||||||
|
relocate("com.github.benmanes.caffeine", "fr.xephi.authme.libs.com.github.benmanes.caffeine")
|
||||||
|
relocate("com.google.common", "fr.xephi.authme.libs.com.google.common")
|
||||||
|
relocate("com.google.thirdparty", "fr.xephi.authme.libs.com.google.thirdparty")
|
||||||
|
relocate("com.google.j2objc", "fr.xephi.authme.libs.com.google.j2objc")
|
||||||
|
relocate("com.google.errorprone", "fr.xephi.authme.libs.com.google.errorprone")
|
||||||
|
relocate("com.google.gson", "fr.xephi.authme.libs.com.google.gson")
|
||||||
|
relocate("org.apache.http", "fr.xephi.authme.libs.org.apache.http")
|
||||||
|
relocate("org.apache.commons", "fr.xephi.authme.libs.org.apache.commons")
|
||||||
|
relocate("waffle", "fr.xephi.authme.libs.waffle")
|
||||||
|
relocate("com.github.benmanes.caffeine", "fr.xephi.authme.libs.com.github.benmanes.caffeine")
|
||||||
|
relocate("ch.jalu", "fr.xephi.authme.libs.ch.jalu")
|
||||||
|
relocate("com.zaxxer.hikari", "fr.xephi.authme.libs.com.zaxxer.hikari")
|
||||||
|
relocate("org.slf4j", "fr.xephi.authme.libs.org.slf4j")
|
||||||
|
relocate("com.maxmind.db", "fr.xephi.authme.libs.com.maxmind.db")
|
||||||
|
relocate("com.ice.tar", "fr.xephi.authme.libs.com.icetar.tar")
|
||||||
|
relocate("net.ricecode.similarity", "fr.xephi.authme.libs.ricecode.net.ricecode.similarity")
|
||||||
|
relocate("de.rtner", "fr.xephi.authme.libs.de.rtner")
|
||||||
|
relocate("org.picketbox", "fr.xephi.authme.libs.org.picketbox")
|
||||||
|
relocate("org.jboss.crypto", "fr.xephi.authme.libs.org.jboss.crypto")
|
||||||
|
relocate("org.jboss.security", "fr.xephi.authme.libs.org.jboss.security")
|
||||||
|
relocate("de.mkammerer", "fr.xephi.authme.libs.de.mkammerer")
|
||||||
|
relocate("com.warrenstrange", "fr.xephi.authme.libs.com.warrenstrange")
|
||||||
|
relocate("javax.inject", "fr.xephi.authme.libs.javax.inject")
|
||||||
|
relocate("at.favre.lib", "fr.xephi.authme.libs.at.favre.lib")
|
||||||
|
relocate("org.postgresql", "fr.xephi.authme.libs.org.postgresql")
|
||||||
|
// bStats metrics class
|
||||||
|
relocate("org.bstats", "fr.xephi.authme.libs.org.bstats")
|
||||||
|
relocate("org.mariadb.jdbc", "fr.xephi.authme.libs.org.mariadb.jdbc")
|
||||||
|
relocate("com.github.Anon8281.universalScheduler", "fr.xephi.authme.libs.com.github.Anon8281.universalScheduler")
|
||||||
|
relocate("com.mysql", "fr.xephi.authme.libs.com.mysql")
|
||||||
|
relocate("com.google.protobuf", "fr.xephi.authme.libs.com.google.protobuf")
|
||||||
|
relocate("io.netty", "fr.xephi.authme.libs.io.netty")
|
||||||
|
relocate("org.apache.commons.validator", "fr.xephi.authme.libs.org.apache.commons.validator")
|
||||||
|
relocate("com.alessiodp.libby", "fr.xephi.authme.libs.com.alessiodp.libby")
|
||||||
|
relocate("net.kyori.adventure", "fr.xephi.authme.libs.net.kyori.adventure")
|
||||||
|
relocate("net.kyori.examination", "fr.xephi.authme.libs.net.kyori.examination")
|
||||||
|
relocate("net.kyori.option", "fr.xephi.authme.libs.net.kyori.option")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
publishing {
|
||||||
|
publications {
|
||||||
|
create<MavenPublication>("maven") {
|
||||||
|
from(components["java"])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -108,4 +108,4 @@ brackets; optional arguments are enclosed in square brackets (`[ ]`).
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Sun Apr 04 21:31:42 CEST 2021
|
This page was automatically generated on the [HaHaWTH/AuthMeReReloaded repository](https://github.com/HaHaWTH/AuthMeReReloaded/tree/master/docs/) on Sun Apr 04 21:31:42 CEST 2021
|
||||||
|
|||||||
+176
-65
@@ -1,7 +1,8 @@
|
|||||||
<!-- AUTO-GENERATED FILE! Do not edit this directly -->
|
<!-- AUTO-GENERATED FILE! Do not edit this directly -->
|
||||||
<!-- File auto-generated on Thu Jul 28 18:11:22 CEST 2022. See docs/config/config.tpl.md -->
|
<!-- File auto-generated on Wed May 29 21:00:00 CST 2024. See docs/config/config.tpl.md -->
|
||||||
|
|
||||||
## AuthMe Configuration
|
## AuthMe Configuration
|
||||||
|
|
||||||
The first time you run AuthMe it will create a config.yml file in the plugins/AuthMe folder,
|
The first time you run AuthMe it will create a config.yml file in the plugins/AuthMe folder,
|
||||||
with which you can configure various settings. The following is the initial contents of
|
with which you can configure various settings. The following is the initial contents of
|
||||||
the generated config.yml file.
|
the generated config.yml file.
|
||||||
@@ -9,16 +10,26 @@ the generated config.yml file.
|
|||||||
```yml
|
```yml
|
||||||
DataSource:
|
DataSource:
|
||||||
# What type of database do you want to use?
|
# What type of database do you want to use?
|
||||||
# Valid values: SQLITE, MARIADB, MYSQL, POSTGRESQL
|
# Valid values: H2, SQLITE, MARIADB, MYSQL, POSTGRESQL
|
||||||
backend: SQLITE
|
backend: SQLITE
|
||||||
# Enable the database caching system, should be disabled on bungeecord environments
|
# Enable the database caching system, should be disabled on bungeecord environments
|
||||||
# or when a website integration is being used.
|
# or when a website integration is being used.
|
||||||
caching: true
|
caching: true
|
||||||
|
# Should we try to use VirtualThreads(Java 21+) for database cache loader?
|
||||||
|
useVirtualThreadsCache: false
|
||||||
# Database host address
|
# Database host address
|
||||||
mySQLHost: 127.0.0.1
|
mySQLHost: 127.0.0.1
|
||||||
# Database port
|
# Database port
|
||||||
mySQLPort: '3306'
|
mySQLPort: '3306'
|
||||||
|
# Replacement of Mysql's useSsl (for MariaDB only).
|
||||||
|
# - disable: No SSL
|
||||||
|
# - trust: Trust blindly (no validation)
|
||||||
|
# - verify_ca: Encryption, certificates validation, BUT no hostname verification
|
||||||
|
# - verify_full: Encryption, certificate validation and hostname validation
|
||||||
|
# Read more: https://bit.ly/mariadb-sslmode
|
||||||
|
MariaDbSslMode: disabled
|
||||||
# Connect to MySQL database over SSL
|
# Connect to MySQL database over SSL
|
||||||
|
# If you're using MariaDB, use sslMode instead
|
||||||
mySQLUseSSL: true
|
mySQLUseSSL: true
|
||||||
# Verification of server's certificate.
|
# Verification of server's certificate.
|
||||||
# We would not recommend to set this option to false.
|
# We would not recommend to set this option to false.
|
||||||
@@ -26,6 +37,7 @@ DataSource:
|
|||||||
mySQLCheckServerCertificate: true
|
mySQLCheckServerCertificate: true
|
||||||
# Authorize client to retrieve RSA server public key.
|
# Authorize client to retrieve RSA server public key.
|
||||||
# Advanced option, ignore if you don't know what it means.
|
# Advanced option, ignore if you don't know what it means.
|
||||||
|
# If you are using MariaDB, use MariaDbSslMode instead.
|
||||||
mySQLAllowPublicKeyRetrieval: true
|
mySQLAllowPublicKeyRetrieval: true
|
||||||
# Username to connect to the MySQL database
|
# Username to connect to the MySQL database
|
||||||
mySQLUsername: authme
|
mySQLUsername: authme
|
||||||
@@ -105,6 +117,64 @@ ExternalBoardOptions:
|
|||||||
XFActivatedGroupId: 2
|
XFActivatedGroupId: 2
|
||||||
# Wordpress prefix defined during WordPress installation
|
# Wordpress prefix defined during WordPress installation
|
||||||
wordpressTablePrefix: wp_
|
wordpressTablePrefix: wp_
|
||||||
|
3rdPartyFeature:
|
||||||
|
compatibility:
|
||||||
|
# Should we execute /help command when unregistered players press Shift+F?
|
||||||
|
# This keeps compatibility with some menu plugins
|
||||||
|
# If you are using TrMenu, don't enable this because TrMenu already implemented this.
|
||||||
|
menuPlugins: false
|
||||||
|
features:
|
||||||
|
i18nMessages:
|
||||||
|
# Send i18n messages to player based on their client settings, this option will override `settings.messagesLanguage`
|
||||||
|
# This will not affect language of authme help command.
|
||||||
|
enabled: false
|
||||||
|
# Redirect locale code to certain AuthMe language code as you want
|
||||||
|
# Minecraft locale list: https://minecraft.wiki/w/Language
|
||||||
|
# AuthMe language code: https://github.com/HaHaWTH/AuthMeReReloaded/blob/master/docs/translations.md
|
||||||
|
# For example, if you want to show Russian messages to player using language Tatar(tt_ru),
|
||||||
|
# and show Chinese Simplified messages to player using language Classical Chinese(lzh), then:
|
||||||
|
# locale-code-redirect:
|
||||||
|
# - 'tt_ru:ru'
|
||||||
|
# - 'lzh:zhcn'
|
||||||
|
locale-code-redirect:
|
||||||
|
- tt_ru:ru
|
||||||
|
- lzh:zhcn
|
||||||
|
captcha:
|
||||||
|
# Should send GUI captcha by country code whitelist?
|
||||||
|
# If the country of the player is in this list, the captcha won't be sent.
|
||||||
|
whiteList: []
|
||||||
|
# Send a GUI captcha to unregistered players?(Requires ProtocolLib)
|
||||||
|
guiCaptcha: false
|
||||||
|
# Should we kick the players when they don't finish the GUI captcha in seconds?
|
||||||
|
# (less than or equals 0 is disabled)
|
||||||
|
timeOut: 0
|
||||||
|
# Should we ignore floodgate players when sending GUI captcha?
|
||||||
|
# (Requires floodgate and hookFloodgate: true)
|
||||||
|
ignoreBedrock: false
|
||||||
|
# Should we let Bedrock players login automatically?
|
||||||
|
# (Requires hookFloodgate to be true & floodgate loaded)
|
||||||
|
# (**THIS IS SAFE DO NOT WORRY**)
|
||||||
|
bedrockAutoLogin: false
|
||||||
|
purgeData:
|
||||||
|
# Should we purge data on non-registered players quit?
|
||||||
|
purgeOnQuit: false
|
||||||
|
# Which world's player data should be deleted?(Enter the world *FOLDER* name where your players first logged in)
|
||||||
|
purgeWorldFolderName: world
|
||||||
|
fixes:
|
||||||
|
# Enable the new feature to prevent ghost players?
|
||||||
|
antiGhostPlayer: false
|
||||||
|
# (MC1.13- only)
|
||||||
|
# Should we fix the shulker crash bug with advanced method?
|
||||||
|
advancedShulkerFix: false
|
||||||
|
loginLocationFix:
|
||||||
|
# Should we fix the location when players logged in the portal?
|
||||||
|
fixPortalStuck: false
|
||||||
|
# Should we fix the location when players logged underground?
|
||||||
|
fixGroundStuck: false
|
||||||
|
optimizes:
|
||||||
|
# Choose the best teleport method by server brand?
|
||||||
|
# (Enable this if you are using Paper/Folia)
|
||||||
|
smartAsyncTeleport: true
|
||||||
settings:
|
settings:
|
||||||
sessions:
|
sessions:
|
||||||
# Do you want to enable the session feature?
|
# Do you want to enable the session feature?
|
||||||
@@ -113,12 +183,13 @@ settings:
|
|||||||
# The next time the player joins the server, if his IP
|
# The next time the player joins the server, if his IP
|
||||||
# is the same as last time and the timeout hasn't
|
# is the same as last time and the timeout hasn't
|
||||||
# expired, he will not need to authenticate.
|
# expired, he will not need to authenticate.
|
||||||
enabled: false
|
enabled: true
|
||||||
# After how many minutes should a session expire?
|
# After how many minutes should a session expire?
|
||||||
# A player's session ends after the timeout or if his IP has changed
|
# A player's session ends after the timeout or if his IP has changed
|
||||||
timeout: 10
|
timeout: 43200
|
||||||
# Message language, available languages:
|
# Message language, available languages:
|
||||||
# https://github.com/AuthMe/AuthMeReloaded/blob/master/docs/translations.md
|
# https://github.com/AuthMe/AuthMeReloaded/blob/master/docs/translations.md
|
||||||
|
# Example: zhcn, en
|
||||||
messagesLanguage: en
|
messagesLanguage: en
|
||||||
# Forces authme to hook into Vault instead of a specific permission handler system.
|
# Forces authme to hook into Vault instead of a specific permission handler system.
|
||||||
forceVaultHook: false
|
forceVaultHook: false
|
||||||
@@ -151,7 +222,7 @@ settings:
|
|||||||
- /totp
|
- /totp
|
||||||
# Max number of allowed registrations per IP
|
# Max number of allowed registrations per IP
|
||||||
# The value 0 means an unlimited number of registrations!
|
# The value 0 means an unlimited number of registrations!
|
||||||
maxRegPerIp: 1
|
maxRegPerIp: 3
|
||||||
# Minimum allowed username length
|
# Minimum allowed username length
|
||||||
minNicknameLength: 3
|
minNicknameLength: 3
|
||||||
# Maximum allowed username length
|
# Maximum allowed username length
|
||||||
@@ -177,7 +248,7 @@ settings:
|
|||||||
SaveQuitLocation: false
|
SaveQuitLocation: false
|
||||||
# To activate the restricted user feature you need
|
# To activate the restricted user feature you need
|
||||||
# to enable this option and configure the AllowedRestrictedUser field.
|
# to enable this option and configure the AllowedRestrictedUser field.
|
||||||
AllowRestrictedUser: false
|
AllowRestrictedUser: true
|
||||||
# The restricted user feature will kick players listed below
|
# The restricted user feature will kick players listed below
|
||||||
# if they don't match the defined IP address. Names are case-insensitive.
|
# if they don't match the defined IP address. Names are case-insensitive.
|
||||||
# You can use * as wildcard (127.0.0.*), or regex with a "regex:" prefix regex:127\.0\.0\..*
|
# You can use * as wildcard (127.0.0.*), or regex with a "regex:" prefix regex:127\.0\.0\..*
|
||||||
@@ -185,13 +256,31 @@ settings:
|
|||||||
# AllowedRestrictedUser:
|
# AllowedRestrictedUser:
|
||||||
# - playername;127.0.0.1
|
# - playername;127.0.0.1
|
||||||
# - playername;regex:127\.0\.0\..*
|
# - playername;regex:127\.0\.0\..*
|
||||||
AllowedRestrictedUser: []
|
AllowedRestrictedUser:
|
||||||
|
- server_land;127.0.0.1
|
||||||
|
- server;127.0.0.1
|
||||||
|
- bukkit;127.0.0.1
|
||||||
|
- purpur;127.0.0.1
|
||||||
|
- system;127.0.0.1
|
||||||
|
- admin;127.0.0.1
|
||||||
|
- md_5;127.0.0.1
|
||||||
|
- administrator;127.0.0.1
|
||||||
|
- notch;127.0.0.1
|
||||||
|
- spigot;127.0.0.1
|
||||||
|
- bukkitcraft;127.0.0.1
|
||||||
|
- paperclip;127.0.0.1
|
||||||
|
- papermc;127.0.0.1
|
||||||
|
- spigotmc;127.0.0.1
|
||||||
|
- root;127.0.0.1
|
||||||
|
- console;127.0.0.1
|
||||||
|
- authme;127.0.0.1
|
||||||
|
- owner;127.0.0.1
|
||||||
# Ban unknown IPs trying to log in with a restricted username?
|
# Ban unknown IPs trying to log in with a restricted username?
|
||||||
banUnsafedIP: false
|
banUnsafedIP: false
|
||||||
# Should unregistered players be kicked immediately?
|
# Should unregistered players be kicked immediately?
|
||||||
kickNonRegistered: false
|
kickNonRegistered: false
|
||||||
# Should players be kicked on wrong password?
|
# Should players be kicked on wrong password?
|
||||||
kickOnWrongPassword: true
|
kickOnWrongPassword: false
|
||||||
# Should not logged in players be teleported to the spawn?
|
# Should not logged in players be teleported to the spawn?
|
||||||
# After the authentication they will be teleported back to
|
# After the authentication they will be teleported back to
|
||||||
# their normal position.
|
# their normal position.
|
||||||
@@ -200,31 +289,33 @@ settings:
|
|||||||
allowMovement: false
|
allowMovement: false
|
||||||
# After how many seconds should players who fail to login or register
|
# After how many seconds should players who fail to login or register
|
||||||
# be kicked? Set to 0 to disable.
|
# be kicked? Set to 0 to disable.
|
||||||
timeout: 30
|
timeout: 120
|
||||||
# Regex pattern of allowed characters in the player name.
|
# Regex pattern of allowed characters in the player name.
|
||||||
allowedNicknameCharacters: '[a-zA-Z0-9_]*'
|
allowedNicknameCharacters: '[a-zA-Z0-9_]*'
|
||||||
# How far can unregistered players walk?
|
# How far can unregistered players walk?
|
||||||
# Set to 0 for unlimited radius
|
# Set to 0 for unlimited radius
|
||||||
allowedMovementRadius: 100
|
allowedMovementRadius: 0
|
||||||
# Should we protect the player inventory before logging in? Requires ProtocolLib.
|
# Should we protect the player inventory before logging in? Requires ProtocolLib.
|
||||||
ProtectInventoryBeforeLogIn: true
|
ProtectInventoryBeforeLogIn: false
|
||||||
# Should we deny the tabcomplete feature before logging in? Requires ProtocolLib.
|
# Should we deny the tabcomplete feature before logging in? Requires ProtocolLib.
|
||||||
DenyTabCompleteBeforeLogin: false
|
DenyTabCompleteBeforeLogin: false
|
||||||
# Should we display all other accounts from a player when he joins?
|
# Should we display all other accounts from a player when he joins?
|
||||||
# permission: /authme.admin.accounts
|
# permission: /authme.admin.accounts
|
||||||
displayOtherAccounts: true
|
displayOtherAccounts: false
|
||||||
# Spawn priority; values: authme, essentials, cmi, multiverse, default
|
# Spawn priority; values: authme, essentials, cmi, multiverse, default
|
||||||
spawnPriority: authme,essentials,cmi,multiverse,default
|
spawnPriority: authme,essentials,cmi,multiverse,default
|
||||||
# Maximum Login authorized by IP
|
# Maximum Login authorized by IP
|
||||||
maxLoginPerIp: 0
|
maxLoginPerIp: 3
|
||||||
# Maximum Join authorized by IP
|
# Maximum Join authorized by IP
|
||||||
maxJoinPerIp: 0
|
maxJoinPerIp: 3
|
||||||
# AuthMe will NEVER teleport players if set to true!
|
# AuthMe will NEVER teleport players if set to true!
|
||||||
noTeleport: false
|
noTeleport: false
|
||||||
# Regex syntax for allowed chars in passwords. The default [!-~] allows all visible ASCII
|
# Regex syntax for allowed chars in passwords. The default [!-~] allows all visible ASCII
|
||||||
# characters, which is what we recommend. See also http://asciitable.com
|
# characters, which is what we recommend. See also http://asciitable.com
|
||||||
# You can test your regex with https://regex101.com
|
# You can test your regex with https://regex101.com
|
||||||
allowedPasswordCharacters: '[!-~]*'
|
allowedPasswordCharacters: '[!-~]*'
|
||||||
|
# Regex syntax for allowed chars in email.
|
||||||
|
allowedEmailCharacters: ^[A-Za-z0-9_.]{3,20}@(qq|outlook|163|gmail|icloud)\.com$
|
||||||
GameMode:
|
GameMode:
|
||||||
# Force survival gamemode when player joins?
|
# Force survival gamemode when player joins?
|
||||||
ForceSurvivalMode: false
|
ForceSurvivalMode: false
|
||||||
@@ -247,12 +338,12 @@ settings:
|
|||||||
UnrestrictedInventories: []
|
UnrestrictedInventories: []
|
||||||
security:
|
security:
|
||||||
# Minimum length of password
|
# Minimum length of password
|
||||||
minPasswordLength: 5
|
minPasswordLength: 8
|
||||||
# Maximum length of password
|
# Maximum length of password
|
||||||
passwordMaxLength: 30
|
passwordMaxLength: 26
|
||||||
# Possible values: SHA256, BCRYPT, BCRYPT2Y, PBKDF2, SALTEDSHA512,
|
# Possible values: SHA256, BCRYPT, BCRYPT2Y, PBKDF2, SALTEDSHA512,
|
||||||
# MYBB, IPB3, PHPBB, PHPFUSION, SMF, XENFORO, XAUTH, JOOMLA, WBB3, WBB4, MD5VB,
|
# MYBB, IPB3, PHPBB, PHPFUSION, SMF, XENFORO, XAUTH, JOOMLA, WBB3, WBB4, MD5VB,
|
||||||
# PBKDF2DJANGO, WORDPRESS, ROYALAUTH, ARGON2, CUSTOM (for developers only). See full list at
|
# PBKDF2DJANGO, WORDPRESS, ROYALAUTH, ARGON2, NOCRYPT, CUSTOM (for developers only). See full list at
|
||||||
# https://github.com/AuthMe/AuthMeReloaded/blob/master/docs/hash_algorithms.md
|
# https://github.com/AuthMe/AuthMeReloaded/blob/master/docs/hash_algorithms.md
|
||||||
# If you use ARGON2, check that you have the argon2 c library on your system
|
# If you use ARGON2, check that you have the argon2 c library on your system
|
||||||
passwordHash: SHA256
|
passwordHash: SHA256
|
||||||
@@ -273,13 +364,19 @@ settings:
|
|||||||
# - 'password'
|
# - 'password'
|
||||||
# - 'help'
|
# - 'help'
|
||||||
unsafePasswords:
|
unsafePasswords:
|
||||||
- '123456'
|
- '12345678'
|
||||||
- password
|
- password
|
||||||
- qwerty
|
- qwertyui
|
||||||
- '12345'
|
|
||||||
- '54321'
|
|
||||||
- '123456789'
|
- '123456789'
|
||||||
- help
|
- '87654321'
|
||||||
|
- '1234567890'
|
||||||
|
- asdfghjkl
|
||||||
|
- zxcvbnm,
|
||||||
|
- asdfghjk
|
||||||
|
- '12312312'
|
||||||
|
- '123123123'
|
||||||
|
- '32132132'
|
||||||
|
- '321321321'
|
||||||
registration:
|
registration:
|
||||||
# Enable registration on the server?
|
# Enable registration on the server?
|
||||||
enabled: true
|
enabled: true
|
||||||
@@ -294,21 +391,26 @@ settings:
|
|||||||
# EMAIL = password is generated and sent to the email provided by the user.
|
# EMAIL = password is generated and sent to the email provided by the user.
|
||||||
# More info at https://github.com/AuthMe/AuthMeReloaded/wiki/Registration
|
# More info at https://github.com/AuthMe/AuthMeReloaded/wiki/Registration
|
||||||
type: PASSWORD
|
type: PASSWORD
|
||||||
# Second argument the /register command should take: NONE = no 2nd argument
|
# Second argument the /register command should take:
|
||||||
|
# NONE = no 2nd argument
|
||||||
# CONFIRMATION = must repeat first argument (pass or email)
|
# CONFIRMATION = must repeat first argument (pass or email)
|
||||||
# EMAIL_OPTIONAL = for password register: 2nd argument can be empty or have email address
|
# EMAIL_OPTIONAL = for password register: 2nd argument can be empty or have email address
|
||||||
# EMAIL_MANDATORY = for password register: 2nd argument MUST be an email address
|
# EMAIL_MANDATORY = for password register: 2nd argument MUST be an email address
|
||||||
secondArg: CONFIRMATION
|
secondArg: CONFIRMATION
|
||||||
|
email:
|
||||||
|
# Should we unregister the player when he didn't verify the email?
|
||||||
|
# This only works if you enabled email registration.
|
||||||
|
unregisterOnEmailVerificationFailure: false
|
||||||
|
# How many minutes should we wait before unregister the player
|
||||||
|
# when he didn't verify the email?
|
||||||
|
unregisterAfterMinutes: 10
|
||||||
# Do we force kick a player after a successful registration?
|
# Do we force kick a player after a successful registration?
|
||||||
# Do not use with login feature below
|
# Do not use with login feature below
|
||||||
forceKickAfterRegister: false
|
forceKickAfterRegister: false
|
||||||
# Does AuthMe need to enforce a /login after a successful registration?
|
# Does AuthMe need to enforce a /login after a successful registration?
|
||||||
forceLoginAfterRegister: false
|
forceLoginAfterRegister: false
|
||||||
# Broadcast the welcome message to the server or only to the player?
|
|
||||||
# set true for server or false for player
|
|
||||||
broadcastWelcomeMessage: false
|
|
||||||
# Should we delay the join message and display it once the player has logged in?
|
# Should we delay the join message and display it once the player has logged in?
|
||||||
delayJoinMessage: false
|
delayJoinMessage: true
|
||||||
# The custom join message that will be sent after a successful login,
|
# The custom join message that will be sent after a successful login,
|
||||||
# keep empty to use the original one.
|
# keep empty to use the original one.
|
||||||
# Available variables:
|
# Available variables:
|
||||||
@@ -317,11 +419,11 @@ settings:
|
|||||||
# {DISPLAYNAMENOCOLOR}: the player display name (without colors)
|
# {DISPLAYNAMENOCOLOR}: the player display name (without colors)
|
||||||
customJoinMessage: ''
|
customJoinMessage: ''
|
||||||
# Should we remove the leave messages of unlogged users?
|
# Should we remove the leave messages of unlogged users?
|
||||||
removeUnloggedLeaveMessage: false
|
removeUnloggedLeaveMessage: true
|
||||||
# Should we remove join messages altogether?
|
# Should we remove join messages altogether?
|
||||||
removeJoinMessage: false
|
removeJoinMessage: true
|
||||||
# Should we remove leave messages altogether?
|
# Should we remove leave messages altogether?
|
||||||
removeLeaveMessage: false
|
removeLeaveMessage: true
|
||||||
# Do we need to add potion effect Blinding before login/register?
|
# Do we need to add potion effect Blinding before login/register?
|
||||||
applyBlindEffect: false
|
applyBlindEffect: false
|
||||||
# Do we need to prevent people to login with another case?
|
# Do we need to prevent people to login with another case?
|
||||||
@@ -347,7 +449,7 @@ GroupOptions:
|
|||||||
unregisteredPlayerGroup: ''
|
unregisteredPlayerGroup: ''
|
||||||
Email:
|
Email:
|
||||||
# Email SMTP server host
|
# Email SMTP server host
|
||||||
mailSMTP: smtp.gmail.com
|
mailSMTP: smtp.163.com
|
||||||
# Email SMTP server port
|
# Email SMTP server port
|
||||||
mailPort: 465
|
mailPort: 465
|
||||||
# Only affects port 25: enable TLS/STARTTLS?
|
# Only affects port 25: enable TLS/STARTTLS?
|
||||||
@@ -361,7 +463,7 @@ Email:
|
|||||||
# Custom sender name, replacing the mailAccount name in the email
|
# Custom sender name, replacing the mailAccount name in the email
|
||||||
mailSenderName: ''
|
mailSenderName: ''
|
||||||
# Recovery password length
|
# Recovery password length
|
||||||
RecoveryPasswordLength: 8
|
RecoveryPasswordLength: 12
|
||||||
# Mail Subject
|
# Mail Subject
|
||||||
mailSubject: Your new AuthMe password
|
mailSubject: Your new AuthMe password
|
||||||
# Like maxRegPerIP but with email
|
# Like maxRegPerIP but with email
|
||||||
@@ -370,20 +472,30 @@ Email:
|
|||||||
recallPlayers: false
|
recallPlayers: false
|
||||||
# Delay in minute for the recall scheduler
|
# Delay in minute for the recall scheduler
|
||||||
delayRecall: 5
|
delayRecall: 5
|
||||||
# Blacklist these domains for emails
|
|
||||||
emailBlacklisted:
|
|
||||||
- 10minutemail.com
|
|
||||||
# Whitelist ONLY these domains for emails
|
|
||||||
emailWhitelisted: []
|
|
||||||
# Send the new password drawn in an image?
|
# Send the new password drawn in an image?
|
||||||
generateImage: false
|
generateImage: false
|
||||||
# The OAuth2 token
|
# The OAuth2 token
|
||||||
emailOauth2Token: ''
|
emailOauth2Token: ''
|
||||||
|
# Email notifications when the server shuts down
|
||||||
|
shutDownEmail: false
|
||||||
|
# Email notification address when the server is shut down
|
||||||
|
shutDownEmailAddress: your@mail.com
|
||||||
Hooks:
|
Hooks:
|
||||||
# Do we need to hook with multiverse for spawn checking?
|
# Do we need to hook with multiverse for spawn checking?
|
||||||
multiverse: true
|
multiverse: true
|
||||||
# Do we need to hook with BungeeCord?
|
# Do we need to hook with BungeeCord?
|
||||||
bungeecord: false
|
bungeecord: false
|
||||||
|
# Do we need to hook with Velocity?
|
||||||
|
velocity: false
|
||||||
|
# How many ticks should we wait before sending login info to proxy?
|
||||||
|
# Change this to higher if your player has high ping.
|
||||||
|
# See: https://www.spigotmc.org/wiki/bukkit-bungee-plugin-messaging-channel/
|
||||||
|
proxySendDelay: 10
|
||||||
|
# Hook into floodgate.
|
||||||
|
# This must be true if you want to use other bedrock features.
|
||||||
|
floodgate: false
|
||||||
|
# Allow bedrock players join without check isValidName?
|
||||||
|
ignoreBedrockNameCheck: true
|
||||||
# Send player to this BungeeCord server after register/login
|
# Send player to this BungeeCord server after register/login
|
||||||
sendPlayerTo: ''
|
sendPlayerTo: ''
|
||||||
# Do we need to disable Essentials SocialSpy on join?
|
# Do we need to disable Essentials SocialSpy on join?
|
||||||
@@ -394,22 +506,12 @@ Protection:
|
|||||||
# Enable some servers protection (country based login, antibot)
|
# Enable some servers protection (country based login, antibot)
|
||||||
enableProtection: false
|
enableProtection: false
|
||||||
# Apply the protection also to registered usernames
|
# Apply the protection also to registered usernames
|
||||||
enableProtectionRegistered: true
|
enableProtectionRegistered: false
|
||||||
geoIpDatabase:
|
|
||||||
# The MaxMind clientId used to download the GeoIp database,
|
|
||||||
# get one at https://www.maxmind.com/en/accounts/current/license-key
|
|
||||||
# The EssentialsX project has a very useful tutorial on how to generate
|
|
||||||
# the license key: https://github.com/EssentialsX/Wiki/blob/master/GeoIP.md
|
|
||||||
clientId: ''
|
|
||||||
# The MaxMind licenseKey used to download the GeoIp database.
|
|
||||||
licenseKey: ''
|
|
||||||
# Countries allowed to join the server and register. For country codes, see
|
# Countries allowed to join the server and register. For country codes, see
|
||||||
# https://dev.maxmind.com/geoip/legacy/codes/iso3166/
|
# https://dev.maxmind.com/geoip/legacy/codes/iso3166/
|
||||||
# Use "LOCALHOST" for local addresses.
|
# Use "LOCALHOST" for local addresses.
|
||||||
# PLEASE USE QUOTES!
|
# PLEASE USE QUOTES!
|
||||||
countries:
|
countries:
|
||||||
- US
|
|
||||||
- GB
|
|
||||||
- LOCALHOST
|
- LOCALHOST
|
||||||
# Countries not allowed to join the server and register
|
# Countries not allowed to join the server and register
|
||||||
# PLEASE USE QUOTES!
|
# PLEASE USE QUOTES!
|
||||||
@@ -428,7 +530,7 @@ Protection:
|
|||||||
antiBotDelay: 60
|
antiBotDelay: 60
|
||||||
quickCommands:
|
quickCommands:
|
||||||
# Kicks the player that issued a command before the defined time after the join process
|
# Kicks the player that issued a command before the defined time after the join process
|
||||||
denyCommandsBeforeMilliseconds: 1000
|
denyCommandsBeforeMilliseconds: 3000
|
||||||
Purge:
|
Purge:
|
||||||
# If enabled, AuthMe automatically purges old, unused accounts
|
# If enabled, AuthMe automatically purges old, unused accounts
|
||||||
useAutoPurge: false
|
useAutoPurge: false
|
||||||
@@ -451,26 +553,33 @@ Security:
|
|||||||
# Stop the server if we can't contact the sql database
|
# Stop the server if we can't contact the sql database
|
||||||
# Take care with this, if you set this to false,
|
# Take care with this, if you set this to false,
|
||||||
# AuthMe will automatically disable and the server won't be protected!
|
# AuthMe will automatically disable and the server won't be protected!
|
||||||
stopServer: true
|
stopServer: false
|
||||||
console:
|
console:
|
||||||
# Copy AuthMe log output in a separate file as well?
|
# Copy AuthMe log output in a separate file as well?
|
||||||
logConsole: true
|
logConsole: true
|
||||||
|
account:
|
||||||
|
haveIBeenPwned:
|
||||||
|
# Query haveibeenpwned.com with a hashed version of the password.
|
||||||
|
# This is used to check whether it is safe.
|
||||||
|
check: false
|
||||||
|
# If the password is used more than this number of times, it is considered unsafe.
|
||||||
|
limit: 0
|
||||||
captcha:
|
captcha:
|
||||||
# Enable captcha when a player uses wrong password too many times
|
# Enable captcha when a player uses wrong password too many times
|
||||||
useCaptcha: false
|
useCaptcha: false
|
||||||
# Max allowed tries before a captcha is required
|
# Max allowed tries before a captcha is required
|
||||||
maxLoginTry: 5
|
maxLoginTry: 8
|
||||||
# Captcha length
|
# Captcha length
|
||||||
captchaLength: 5
|
captchaLength: 6
|
||||||
# Minutes after which login attempts count is reset for a player
|
# Minutes after which login attempts count is reset for a player
|
||||||
captchaCountReset: 60
|
captchaCountReset: 120
|
||||||
# Require captcha before a player may register?
|
# Require captcha before a player may register?
|
||||||
requireForRegistration: false
|
requireForRegistration: false
|
||||||
tempban:
|
tempban:
|
||||||
# Tempban a user's IP address if they enter the wrong password too many times
|
# Tempban a user's IP address if they enter the wrong password too many times
|
||||||
enableTempban: false
|
enableTempban: false
|
||||||
# How many times a user can attempt to login before their IP being tempbanned
|
# How many times a user can attempt to login before their IP being tempbanned
|
||||||
maxLoginTries: 10
|
maxLoginTries: 8
|
||||||
# The length of time a IP address will be tempbanned in minutes
|
# The length of time a IP address will be tempbanned in minutes
|
||||||
# Default: 480 minutes, or 8 hours
|
# Default: 480 minutes, or 8 hours
|
||||||
tempbanLength: 480
|
tempbanLength: 480
|
||||||
@@ -484,13 +593,13 @@ Security:
|
|||||||
# Number of characters a recovery code should have (0 to disable)
|
# Number of characters a recovery code should have (0 to disable)
|
||||||
length: 8
|
length: 8
|
||||||
# How many hours is a recovery code valid for?
|
# How many hours is a recovery code valid for?
|
||||||
validForHours: 4
|
validForHours: 6
|
||||||
# Max number of tries to enter recovery code
|
# Max number of tries to enter recovery code
|
||||||
maxTries: 3
|
maxTries: 4
|
||||||
# How long a player has after password recovery to change their password
|
# How long a player has after password recovery to change their password
|
||||||
# without logging in. This is in minutes.
|
# without logging in. This is in minutes.
|
||||||
# Default: 2 minutes
|
# Default: 2 minutes
|
||||||
passwordChangeTimeout: 2
|
passwordChangeTimeout: 5
|
||||||
emailRecovery:
|
emailRecovery:
|
||||||
# Seconds a user has to wait for before a password recovery mail may be sent again
|
# Seconds a user has to wait for before a password recovery mail may be sent again
|
||||||
# This prevents an attacker from abusing AuthMe's email feature.
|
# This prevents an attacker from abusing AuthMe's email feature.
|
||||||
@@ -503,6 +612,13 @@ Security:
|
|||||||
enableEmailMasking: false
|
enableEmailMasking: false
|
||||||
# Minutes after which a verification code will expire
|
# Minutes after which a verification code will expire
|
||||||
verificationCodeExpiration: 10
|
verificationCodeExpiration: 10
|
||||||
|
Plugin:
|
||||||
|
updates:
|
||||||
|
# Check for updates on enabled from GitHub?
|
||||||
|
checkForUpdates: true
|
||||||
|
banners:
|
||||||
|
# Should we show the AuthMe banner on startup?
|
||||||
|
showBanners: true
|
||||||
# Before a user logs in, various properties are temporarily removed from the player,
|
# Before a user logs in, various properties are temporarily removed from the player,
|
||||||
# such as OP status, ability to fly, and walk/fly speed.
|
# such as OP status, ability to fly, and walk/fly speed.
|
||||||
# Once the user is logged in, we add back the properties we previously saved.
|
# Once the user is logged in, we add back the properties we previously saved.
|
||||||
@@ -551,13 +667,6 @@ BackupSystem:
|
|||||||
MysqlWindowsPath: C:\Program Files\MySQL\MySQL Server 5.1\
|
MysqlWindowsPath: C:\Program Files\MySQL\MySQL Server 5.1\
|
||||||
# Converter settings: see https://github.com/AuthMe/AuthMeReloaded/wiki/Converters
|
# Converter settings: see https://github.com/AuthMe/AuthMeReloaded/wiki/Converters
|
||||||
Converter:
|
Converter:
|
||||||
Rakamak:
|
|
||||||
# Rakamak file name
|
|
||||||
fileName: users.rak
|
|
||||||
# Rakamak use IP?
|
|
||||||
useIP: false
|
|
||||||
# Rakamak IP file name
|
|
||||||
ipFileName: UsersIp.rak
|
|
||||||
CrazyLogin:
|
CrazyLogin:
|
||||||
# CrazyLogin database file name
|
# CrazyLogin database file name
|
||||||
fileName: accounts.db
|
fileName: accounts.db
|
||||||
@@ -581,4 +690,6 @@ To change settings on a running server, save your changes to config.yml and use
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Thu Jul 28 18:11:22 CEST 2022
|
This page was automatically generated on
|
||||||
|
the [HaHaWTH/AuthMeReReloaded repository](https://github.com/HaHaWTH/AuthMeReReloaded/tree/master/docs/) on Wed May 29
|
||||||
|
21:00:00 CST 2024
|
||||||
|
|||||||
@@ -80,4 +80,4 @@ or bad.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Sun Apr 04 21:31:44 CEST 2021
|
This page was automatically generated on the [HaHaWTH/AuthMeReReloaded repository](https://github.com/HaHaWTH/AuthMeReReloaded/tree/master/docs/) on Sun Apr 04 21:31:44 CEST 2021
|
||||||
|
|||||||
@@ -73,4 +73,4 @@ The following are the permission nodes that are currently supported by the lates
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Sun Apr 04 21:31:44 CEST 2021
|
This page was automatically generated on the [HaHaWTH/AuthMeReReloaded repository](https://github.com/HaHaWTH/AuthMeReReloaded/tree/master/docs/) on Sun Apr 04 21:31:44 CEST 2021
|
||||||
|
|||||||
+40
-37
@@ -1,46 +1,49 @@
|
|||||||
<!-- AUTO-GENERATED FILE! Do not edit this directly -->
|
<!-- AUTO-GENERATED FILE! Do not edit this directly -->
|
||||||
<!-- File auto-generated on Sun Apr 04 21:31:44 CEST 2021. See docs/translations/translations.tpl.md -->
|
<!-- File auto-generated on Fri May 31 22:00:00 CST 2024. See docs/translations/translations.tpl.md -->
|
||||||
|
|
||||||
# AuthMe Translations
|
# AuthMe Translations
|
||||||
|
|
||||||
The following translations are available in AuthMe. Set `messagesLanguage` to the language code
|
The following translations are available in AuthMe. Set `messagesLanguage` to the language code
|
||||||
in your config.yml to use the language, or use another language code to start a new translation.
|
in your config.yml to use the language, or use another language code to start a new translation.
|
||||||
|
|
||||||
Code | Language | Translated |
|
| Code | Language | Translated | |
|
||||||
---- | -------- | ---------: | ------
|
|------------------------------------------------------------------------------------------------------------|---------------------|-----------:|---------------------------------------------------------------------------|
|
||||||
[en](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_en.yml) | English | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" />
|
| [en](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_en.yml) | English | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" /> |
|
||||||
[bg](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_bg.yml) | Bulgarian | 99% | <img src="https://via.placeholder.com/99x7/66ee55?text=%20" alt="99" />
|
| [bg](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_bg.yml) | Bulgarian | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" /> |
|
||||||
[br](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_br.yml) | Brazilian | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" />
|
| [br](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_br.yml) | Brazilian | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" /> |
|
||||||
[cz](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_cz.yml) | Czech | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" />
|
| [cz](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_cz.yml) | Czech | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" /> |
|
||||||
[de](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_de.yml) | German | 99% | <img src="https://via.placeholder.com/99x7/66ee55?text=%20" alt="99" />
|
| [de](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_de.yml) | German | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" /> |
|
||||||
[eo](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_eo.yml) | Esperanto | 79% | <img src="https://via.placeholder.com/79x7/bb9900?text=%20" alt="79" />
|
| [eo](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_eo.yml) | Esperanto | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" /> |
|
||||||
[es](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_es.yml) | Spanish | 99% | <img src="https://via.placeholder.com/99x7/66ee55?text=%20" alt="99" />
|
| [es](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_es.yml) | Spanish | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" /> |
|
||||||
[et](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_et.yml) | Estonian | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" />
|
| [et](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_et.yml) | Estonian | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" /> |
|
||||||
[eu](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_eu.yml) | Basque | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" />
|
| [eu](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_eu.yml) | Basque | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" /> |
|
||||||
[fi](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_fi.yml) | Finnish | 45% | <img src="https://via.placeholder.com/45x7/aa5500?text=%20" alt="45" />
|
| [fi](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_fi.yml) | Finnish | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" /> |
|
||||||
[fr](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_fr.yml) | French | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" />
|
| [fr](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_fr.yml) | French | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" /> |
|
||||||
[gl](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_gl.yml) | Galician | 48% | <img src="https://via.placeholder.com/48x7/aa5500?text=%20" alt="48" />
|
| [gl](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_gl.yml) | Galician | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" /> |
|
||||||
[hu](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_hu.yml) | Hungarian | 99% | <img src="https://via.placeholder.com/99x7/66ee55?text=%20" alt="99" />
|
| [hu](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_hu.yml) | Hungarian | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" /> |
|
||||||
[id](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_id.yml) | Indonesian | 93% | <img src="https://via.placeholder.com/93x7/77dd44?text=%20" alt="93" />
|
| [id](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_id.yml) | Indonesian | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" /> |
|
||||||
[it](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_it.yml) | Italian | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" />
|
| [it](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_it.yml) | Italian | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" /> |
|
||||||
[ko](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_ko.yml) | Korean | 99% | <img src="https://via.placeholder.com/99x7/66ee55?text=%20" alt="99" />
|
| [ja](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_ja.yml) | Japanese | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" /> |
|
||||||
[lt](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_lt.yml) | Lithuanian | 36% | <img src="https://via.placeholder.com/36x7/aa4400?text=%20" alt="36" />
|
| [ko](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_ko.yml) | Korean | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" /> |
|
||||||
[nl](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_nl.yml) | Dutch | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" />
|
| [lt](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_lt.yml) | Lithuanian | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" /> |
|
||||||
[pl](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_pl.yml) | Polish | 99% | <img src="https://via.placeholder.com/99x7/66ee55?text=%20" alt="99" />
|
| [nl](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_nl.yml) | Dutch | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" /> |
|
||||||
[pt](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_pt.yml) | Portuguese | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" />
|
| [pl](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_pl.yml) | Polish | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" /> |
|
||||||
[ro](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_ro.yml) | Romanian | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" />
|
| [pt](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_pt.yml) | Portuguese | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" /> |
|
||||||
[ru](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_ru.yml) | Russian | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" />
|
| [ro](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_ro.yml) | Romanian | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" /> |
|
||||||
[si](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_si.yml) | Slovenian | 99% | <img src="https://via.placeholder.com/99x7/66ee55?text=%20" alt="99" />
|
| [ru](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_ru.yml) | Russian | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" /> |
|
||||||
[sk](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_sk.yml) | Slovakian | 79% | <img src="https://via.placeholder.com/79x7/bb9900?text=%20" alt="79" />
|
| [si](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_si.yml) | Slovenian | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" /> |
|
||||||
[sr](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_sr.yml) | Serbian | 99% | <img src="https://via.placeholder.com/99x7/66ee55?text=%20" alt="99" />
|
| [sk](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_sk.yml) | Slovakian | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" /> |
|
||||||
[tr](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_tr.yml) | Turkish | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" />
|
| [sr](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_sr.yml) | Serbian | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" /> |
|
||||||
[uk](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_uk.yml) | Ukrainian | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" />
|
| [tr](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_tr.yml) | Turkish | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" /> |
|
||||||
[vn](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_vn.yml) | Vietnamese | 77% | <img src="https://via.placeholder.com/77x7/bb9900?text=%20" alt="77" />
|
| [uk](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_uk.yml) | Ukrainian | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" /> |
|
||||||
[zhcn](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_zhcn.yml) | Chinese (China) | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" />
|
| [vn](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_vn.yml) | Vietnamese | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" /> |
|
||||||
[zhhk](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_zhhk.yml) | Chinese (Hong Kong) | 99% | <img src="https://via.placeholder.com/99x7/66ee55?text=%20" alt="99" />
|
| [zhcn](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_zhcn.yml) | Chinese (China) | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" /> |
|
||||||
[zhmc](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_zhmc.yml) | Chinese (Macau) | 64% | <img src="https://via.placeholder.com/64x7/bb7700?text=%20" alt="64" />
|
| [zhhk](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_zhhk.yml) | Chinese (Hong Kong) | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" /> |
|
||||||
[zhtw](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_zhtw.yml) | Chinese (Taiwan) | 86% | <img src="https://via.placeholder.com/86x7/99bb22?text=%20" alt="86" />
|
| [zhmc](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_zhmc.yml) | Chinese (Macau) | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" /> |
|
||||||
|
| [zhtw](https://github.com/AuthMe/AuthMeReloaded/blob/master/src/main/resources/messages/messages_zhtw.yml) | Chinese (Taiwan) | 100% | <img src="https://via.placeholder.com/100x7/66ff66?text=%20" alt="100" /> |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
This page was automatically generated on the [AuthMe/AuthMeReloaded repository](https://github.com/AuthMe/AuthMeReloaded/tree/master/docs/) on Sun Apr 04 21:31:44 CEST 2021
|
This page was automatically generated on
|
||||||
|
the [HaHaWTH/AuthMeReReloaded repository](https://github.com/HaHaWTH/AuthMeReReloaded/tree/master/docs/) on Fri May 31
|
||||||
|
22:00:00 CST 2024
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
group=fr.xephi
|
||||||
|
version=5.7.0-FORK-b53
|
||||||
|
mainClass = fr.xephi.authme.AuthMe
|
||||||
|
authors = [sgdc3, games647, Hex3l, krusic22]
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
[versions]
|
||||||
|
adventureApi = "4.18.0"
|
||||||
|
adventurePlatform = "4.3.4"
|
||||||
|
injector = "1.0"
|
||||||
|
string-similarity = "1.0.0"
|
||||||
|
maxmind-db-gson = "2.0.3"
|
||||||
|
javatar = "2.5"
|
||||||
|
commons-email = "1.6-SNAPSHOT"
|
||||||
|
log4j-core = "2.20.0"
|
||||||
|
libby-bukkit = "2.0.0-SNAPSHOT"
|
||||||
|
hikaricp = "4.0.3"
|
||||||
|
slf4j-simple = "1.7.36"
|
||||||
|
pbkdf2 = "1.1.4"
|
||||||
|
mysql-connector-j = "9.1.0"
|
||||||
|
mariadb-java-client = "3.5.1"
|
||||||
|
argon2-jvm-nolibs = "2.11"
|
||||||
|
googleauth = "1.5.0"
|
||||||
|
guava = "33.2.1-jre"
|
||||||
|
gson = "2.10.1"
|
||||||
|
configme = "1.3.1"
|
||||||
|
bcrypt = "0.10.2"
|
||||||
|
datasourcecolumns = "0.1.1-SNAPSHOT"
|
||||||
|
postgresql = "42.7.4"
|
||||||
|
checker-qual = "3.48.0"
|
||||||
|
universalscheduler = "0.1.6"
|
||||||
|
sqlite-jdbc = "3.47.1.0"
|
||||||
|
h2 = "2.2.224"
|
||||||
|
|
||||||
|
[libraries]
|
||||||
|
adventure-text-minimessage = { group = "net.kyori", name = "adventure-text-minimessage", version.ref = "adventureApi" }
|
||||||
|
adventure-platform-bukkit = { group = "net.kyori", name = "adventure-platform-bukkit", version.ref = "adventurePlatform" }
|
||||||
|
adventure-text-serializer-gson = { group = "net.kyori", name = "adventure-text-serializer-gson", version.ref = "adventureApi" }
|
||||||
|
injector = { group = "ch.jalu", name = "injector", version.ref = "injector" }
|
||||||
|
string-similarity = { group = "net.ricecode", name = "string-similarity", version.ref = "string-similarity" }
|
||||||
|
maxmind-db-gson = { group = "com.maxmind.db", name = "maxmind-db-gson", version.ref = "maxmind-db-gson" }
|
||||||
|
javatar = { group = "javatar", name = "javatar", version.ref = "javatar" }
|
||||||
|
commons-email = { group = "org.apache.commons", name = "commons-email", version.ref = "commons-email" }
|
||||||
|
log4j-core = { group = "org.apache.logging.log4j", name = "log4j-core", version.ref = "log4j-core" }
|
||||||
|
libby-bukkit = { group = "com.alessiodp.libby", name = "libby-bukkit", version.ref = "libby-bukkit" }
|
||||||
|
hikaricp = { group = "com.zaxxer", name = "HikariCP", version.ref = "hikaricp" }
|
||||||
|
slf4j-simple = { group = "org.slf4j", name = "slf4j-simple", version.ref = "slf4j-simple" }
|
||||||
|
pbkdf2 = { group = "de.rtner", name = "PBKDF2", version.ref = "pbkdf2" }
|
||||||
|
mysql-connector-j = { group = "com.mysql", name = "mysql-connector-j", version.ref = "mysql-connector-j" }
|
||||||
|
mariadb-java-client = { group = "org.mariadb.jdbc", name = "mariadb-java-client", version.ref = "mariadb-java-client" }
|
||||||
|
argon2-jvm-nolibs = { group = "de.mkammerer", name = "argon2-jvm-nolibs", version.ref = "argon2-jvm-nolibs" }
|
||||||
|
googleauth = { group = "com.warrenstrange", name = "googleauth", version.ref = "googleauth" }
|
||||||
|
guava = { group = "com.google.guava", name = "guava", version.ref = "guava" }
|
||||||
|
gson = { group = "com.google.code.gson", name = "gson", version.ref = "gson" }
|
||||||
|
configme = { group = "ch.jalu", name = "configme", version.ref = "configme" }
|
||||||
|
bcrypt = { group = "at.favre.lib", name = "bcrypt", version.ref = "bcrypt" }
|
||||||
|
datasourcecolumns = { group = "ch.jalu", name = "datasourcecolumns", version.ref = "datasourcecolumns" }
|
||||||
|
postgresql = { group = "org.postgresql", name = "postgresql", version.ref = "postgresql" }
|
||||||
|
checker-qual = { group = "org.checkerframework", name = "checker-qual", version.ref = "checker-qual" }
|
||||||
|
universalscheduler = { group = "com.github.Anon8281", name = "UniversalScheduler", version.ref = "universalscheduler" }
|
||||||
|
sqlite-jdbc = { group = "org.xerial", name = "sqlite-jdbc", version.ref = "sqlite-jdbc" }
|
||||||
|
h2 = { group = "com.h2database", name = "h2", version.ref = "h2" }
|
||||||
Vendored
BIN
Binary file not shown.
+7
@@ -0,0 +1,7 @@
|
|||||||
|
distributionBase=GRADLE_USER_HOME
|
||||||
|
distributionPath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-bin.zip
|
||||||
|
networkTimeout=10000
|
||||||
|
validateDistributionUrl=true
|
||||||
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
zipStorePath=wrapper/dists
|
||||||
@@ -0,0 +1,251 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copyright © 2015-2021 the original authors.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
#
|
||||||
|
# Gradle start up script for POSIX generated by Gradle.
|
||||||
|
#
|
||||||
|
# Important for running:
|
||||||
|
#
|
||||||
|
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||||
|
# noncompliant, but you have some other compliant shell such as ksh or
|
||||||
|
# bash, then to run this script, type that shell name before the whole
|
||||||
|
# command line, like:
|
||||||
|
#
|
||||||
|
# ksh Gradle
|
||||||
|
#
|
||||||
|
# Busybox and similar reduced shells will NOT work, because this script
|
||||||
|
# requires all of these POSIX shell features:
|
||||||
|
# * functions;
|
||||||
|
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||||
|
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||||
|
# * compound commands having a testable exit status, especially «case»;
|
||||||
|
# * various built-in commands including «command», «set», and «ulimit».
|
||||||
|
#
|
||||||
|
# Important for patching:
|
||||||
|
#
|
||||||
|
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||||
|
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||||
|
#
|
||||||
|
# The "traditional" practice of packing multiple parameters into a
|
||||||
|
# space-separated string is a well documented source of bugs and security
|
||||||
|
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||||
|
# options in "$@", and eventually passing that to Java.
|
||||||
|
#
|
||||||
|
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||||
|
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||||
|
# see the in-line comments for details.
|
||||||
|
#
|
||||||
|
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||||
|
# Darwin, MinGW, and NonStop.
|
||||||
|
#
|
||||||
|
# (3) This script is generated from the Groovy template
|
||||||
|
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||||
|
# within the Gradle project.
|
||||||
|
#
|
||||||
|
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||||
|
#
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
# Attempt to set APP_HOME
|
||||||
|
|
||||||
|
# Resolve links: $0 may be a link
|
||||||
|
app_path=$0
|
||||||
|
|
||||||
|
# Need this for daisy-chained symlinks.
|
||||||
|
while
|
||||||
|
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||||
|
[ -h "$app_path" ]
|
||||||
|
do
|
||||||
|
ls=$( ls -ld "$app_path" )
|
||||||
|
link=${ls#*' -> '}
|
||||||
|
case $link in #(
|
||||||
|
/*) app_path=$link ;; #(
|
||||||
|
*) app_path=$APP_HOME$link ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# This is normally unused
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
APP_BASE_NAME=${0##*/}
|
||||||
|
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||||
|
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
|
||||||
|
|
||||||
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
|
MAX_FD=maximum
|
||||||
|
|
||||||
|
warn () {
|
||||||
|
echo "$*"
|
||||||
|
} >&2
|
||||||
|
|
||||||
|
die () {
|
||||||
|
echo
|
||||||
|
echo "$*"
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
} >&2
|
||||||
|
|
||||||
|
# OS specific support (must be 'true' or 'false').
|
||||||
|
cygwin=false
|
||||||
|
msys=false
|
||||||
|
darwin=false
|
||||||
|
nonstop=false
|
||||||
|
case "$( uname )" in #(
|
||||||
|
CYGWIN* ) cygwin=true ;; #(
|
||||||
|
Darwin* ) darwin=true ;; #(
|
||||||
|
MSYS* | MINGW* ) msys=true ;; #(
|
||||||
|
NONSTOP* ) nonstop=true ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
|
|
||||||
|
# Determine the Java command to use to start the JVM.
|
||||||
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
|
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||||
|
else
|
||||||
|
JAVACMD=$JAVA_HOME/bin/java
|
||||||
|
fi
|
||||||
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
|
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
JAVACMD=java
|
||||||
|
if ! command -v java >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Increase the maximum file descriptors if we can.
|
||||||
|
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||||
|
case $MAX_FD in #(
|
||||||
|
max*)
|
||||||
|
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||||
|
# shellcheck disable=SC2039,SC3045
|
||||||
|
MAX_FD=$( ulimit -H -n ) ||
|
||||||
|
warn "Could not query maximum file descriptor limit"
|
||||||
|
esac
|
||||||
|
case $MAX_FD in #(
|
||||||
|
'' | soft) :;; #(
|
||||||
|
*)
|
||||||
|
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||||
|
# shellcheck disable=SC2039,SC3045
|
||||||
|
ulimit -n "$MAX_FD" ||
|
||||||
|
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Collect all arguments for the java command, stacking in reverse order:
|
||||||
|
# * args from the command line
|
||||||
|
# * the main class name
|
||||||
|
# * -classpath
|
||||||
|
# * -D...appname settings
|
||||||
|
# * --module-path (only if needed)
|
||||||
|
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||||
|
|
||||||
|
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||||
|
if "$cygwin" || "$msys" ; then
|
||||||
|
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||||
|
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||||
|
|
||||||
|
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||||
|
|
||||||
|
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||||
|
for arg do
|
||||||
|
if
|
||||||
|
case $arg in #(
|
||||||
|
-*) false ;; # don't mess with options #(
|
||||||
|
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||||
|
[ -e "$t" ] ;; #(
|
||||||
|
*) false ;;
|
||||||
|
esac
|
||||||
|
then
|
||||||
|
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||||
|
fi
|
||||||
|
# Roll the args list around exactly as many times as the number of
|
||||||
|
# args, so each arg winds up back in the position where it started, but
|
||||||
|
# possibly modified.
|
||||||
|
#
|
||||||
|
# NB: a `for` loop captures its iteration list before it begins, so
|
||||||
|
# changing the positional parameters here affects neither the number of
|
||||||
|
# iterations, nor the values presented in `arg`.
|
||||||
|
shift # remove old arg
|
||||||
|
set -- "$@" "$arg" # push replacement arg
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||||
|
|
||||||
|
# Collect all arguments for the java command:
|
||||||
|
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||||
|
# and any embedded shellness will be escaped.
|
||||||
|
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||||
|
# treated as '${Hostname}' itself on the command line.
|
||||||
|
|
||||||
|
set -- \
|
||||||
|
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||||
|
-classpath "$CLASSPATH" \
|
||||||
|
org.gradle.wrapper.GradleWrapperMain \
|
||||||
|
"$@"
|
||||||
|
|
||||||
|
# Stop when "xargs" is not available.
|
||||||
|
if ! command -v xargs >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
die "xargs is not available"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Use "xargs" to parse quoted args.
|
||||||
|
#
|
||||||
|
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||||
|
#
|
||||||
|
# In Bash we could simply go:
|
||||||
|
#
|
||||||
|
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||||
|
# set -- "${ARGS[@]}" "$@"
|
||||||
|
#
|
||||||
|
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||||
|
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||||
|
# character that might be a shell metacharacter, then use eval to reverse
|
||||||
|
# that process (while maintaining the separation between arguments), and wrap
|
||||||
|
# the whole thing up as a single "set" statement.
|
||||||
|
#
|
||||||
|
# This will of course break if any of these variables contains a newline or
|
||||||
|
# an unmatched quote.
|
||||||
|
#
|
||||||
|
|
||||||
|
eval "set -- $(
|
||||||
|
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||||
|
xargs -n1 |
|
||||||
|
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||||
|
tr '\n' ' '
|
||||||
|
)" '"$@"'
|
||||||
|
|
||||||
|
exec "$JAVACMD" "$@"
|
||||||
Vendored
+94
@@ -0,0 +1,94 @@
|
|||||||
|
@rem
|
||||||
|
@rem Copyright 2015 the original author or authors.
|
||||||
|
@rem
|
||||||
|
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
@rem you may not use this file except in compliance with the License.
|
||||||
|
@rem You may obtain a copy of the License at
|
||||||
|
@rem
|
||||||
|
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
@rem
|
||||||
|
@rem Unless required by applicable law or agreed to in writing, software
|
||||||
|
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@rem See the License for the specific language governing permissions and
|
||||||
|
@rem limitations under the License.
|
||||||
|
@rem
|
||||||
|
@rem SPDX-License-Identifier: Apache-2.0
|
||||||
|
@rem
|
||||||
|
|
||||||
|
@if "%DEBUG%"=="" @echo off
|
||||||
|
@rem ##########################################################################
|
||||||
|
@rem
|
||||||
|
@rem Gradle startup script for Windows
|
||||||
|
@rem
|
||||||
|
@rem ##########################################################################
|
||||||
|
|
||||||
|
@rem Set local scope for the variables with windows NT shell
|
||||||
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
|
set DIRNAME=%~dp0
|
||||||
|
if "%DIRNAME%"=="" set DIRNAME=.
|
||||||
|
@rem This is normally unused
|
||||||
|
set APP_BASE_NAME=%~n0
|
||||||
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
|
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||||
|
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||||
|
|
||||||
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||||
|
|
||||||
|
@rem Find java.exe
|
||||||
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
|
set JAVA_EXE=java.exe
|
||||||
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
|
if %ERRORLEVEL% equ 0 goto execute
|
||||||
|
|
||||||
|
echo. 1>&2
|
||||||
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||||
|
echo. 1>&2
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||||
|
echo location of your Java installation. 1>&2
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:findJavaFromJavaHome
|
||||||
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
|
if exist "%JAVA_EXE%" goto execute
|
||||||
|
|
||||||
|
echo. 1>&2
|
||||||
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||||
|
echo. 1>&2
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||||
|
echo location of your Java installation. 1>&2
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:execute
|
||||||
|
@rem Setup the command line
|
||||||
|
|
||||||
|
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||||
|
|
||||||
|
|
||||||
|
@rem Execute Gradle
|
||||||
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||||
|
|
||||||
|
:end
|
||||||
|
@rem End local scope for the variables with windows NT shell
|
||||||
|
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||||
|
|
||||||
|
:fail
|
||||||
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
|
rem the _cmd.exe /c_ return code!
|
||||||
|
set EXIT_CODE=%ERRORLEVEL%
|
||||||
|
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||||
|
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||||
|
exit /b %EXIT_CODE%
|
||||||
|
|
||||||
|
:mainEnd
|
||||||
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|
||||||
|
:omega
|
||||||
@@ -1,564 +0,0 @@
|
|||||||
# =======================================================================================================
|
|
||||||
# _____ __ .__ _____ __________ .__ .___ .___
|
|
||||||
# / _ \ __ ___/ |_| |__ / \ ____\______ \ ____ | | _________ __| _/____ __| _/
|
|
||||||
# / /_\ \| | \ __| | \ / \ / \_/ __ \| __/ __ \| | / _ \__ \ / __ _/ __ \ / __ |
|
|
||||||
# / | | | /| | | Y / Y \ ___/| | \ ___/| |_( <_> / __ \/ /_/ \ ___// /_/ |
|
|
||||||
# \____|__ |____/ |__| |___| \____|__ /\___ |____|_ /\___ |____/\____(____ \____ |\___ \____ |
|
|
||||||
# \/ \/ \/ \/ \/ \/ \/ \/ \/ \/
|
|
||||||
#
|
|
||||||
# =======================================================================================================
|
|
||||||
#
|
|
||||||
# Authme Main Configuration File.
|
|
||||||
#
|
|
||||||
# =======================================================================================================
|
|
||||||
|
|
||||||
# Plugin infos (overwritten on start, just a simple way to find out your plugin version).
|
|
||||||
authors: ${pluginAuthors}
|
|
||||||
version: ${project.version}
|
|
||||||
buildNumber: ${buildNumber}
|
|
||||||
|
|
||||||
# Set this setting to true when you have configured the plugin,
|
|
||||||
# when false the server will be stopped with a warning message.
|
|
||||||
enabled: false
|
|
||||||
|
|
||||||
# Database settings.
|
|
||||||
data_source:
|
|
||||||
# ===========================
|
|
||||||
# Database general settings.
|
|
||||||
# ===========================
|
|
||||||
|
|
||||||
# Database backend (sqlite, mysql).
|
|
||||||
backend: sqlite
|
|
||||||
# Enable database queries caching, should improve performance.
|
|
||||||
caching: true
|
|
||||||
|
|
||||||
# ===========================
|
|
||||||
# SqLite db parameters.
|
|
||||||
# ===========================
|
|
||||||
|
|
||||||
sqlite:
|
|
||||||
# The name of the database storage file.
|
|
||||||
filename: 'authme.db'
|
|
||||||
|
|
||||||
# ===========================
|
|
||||||
# MySql db parameters.
|
|
||||||
# ===========================
|
|
||||||
|
|
||||||
mysql:
|
|
||||||
# Connection parameters.
|
|
||||||
host: '127.0.0.1'
|
|
||||||
port: 3306
|
|
||||||
username: 'change_me'
|
|
||||||
password: 'change_me'
|
|
||||||
database: 'my_minecraft_server'
|
|
||||||
tablename: 'authme'
|
|
||||||
|
|
||||||
# Column names.
|
|
||||||
column_names:
|
|
||||||
id: id
|
|
||||||
# Column for storing nicknames (ignore case nickname).
|
|
||||||
name: username
|
|
||||||
# Column for storing the realname (case sensitive nickname).
|
|
||||||
real_name: realname
|
|
||||||
# Column for storing passwords.
|
|
||||||
password: password
|
|
||||||
# Column for storing email addresses.
|
|
||||||
email: email
|
|
||||||
# Column for storing the authentication status (logged or not).
|
|
||||||
login_status: isLogged
|
|
||||||
# Column for storing player IPs.
|
|
||||||
ip: ip
|
|
||||||
# Column for storing lastlogins date and time.
|
|
||||||
last_login_timestamp: lastlogin
|
|
||||||
# Latest logout location of the players.
|
|
||||||
last_location:
|
|
||||||
world: world
|
|
||||||
x: x
|
|
||||||
y: y
|
|
||||||
z: z
|
|
||||||
# Enabled only if the bungeecord integration is activated.
|
|
||||||
server: world
|
|
||||||
|
|
||||||
# Support for registrations via WebInterfaces/CSM.
|
|
||||||
# Disable some backend caching parameters.
|
|
||||||
disableAggressiveCaching: false
|
|
||||||
|
|
||||||
# Main settings
|
|
||||||
settings:
|
|
||||||
|
|
||||||
# ===========================
|
|
||||||
# Bungeecord integration
|
|
||||||
# ===========================
|
|
||||||
|
|
||||||
bungeecord:
|
|
||||||
# Enable bungeecord integration features
|
|
||||||
enabled: true
|
|
||||||
|
|
||||||
# Server name (must be unique, please use the name in the bungeecord configuration).
|
|
||||||
# Use 'auto' for auto configuration (requires the bungeecord module).
|
|
||||||
serverName: LoginLobby1
|
|
||||||
# Keep the auth status when the player moves between servers.
|
|
||||||
# Required if you're using the bungeecord module.
|
|
||||||
keepAuthBetweenServers: true
|
|
||||||
|
|
||||||
# Target server after login
|
|
||||||
send_after_login:
|
|
||||||
enabled: false
|
|
||||||
message: ''
|
|
||||||
delay: 5
|
|
||||||
# Server name ("ServerName") or group ("G:GroupName")
|
|
||||||
# Groups are avariable only when the bungeecord module is avariable.
|
|
||||||
# If the server change fails the player will be kicked.
|
|
||||||
target: Lobby1
|
|
||||||
failKickMessage: 'Failed to connect to the lobby! Please try to join the server again!'
|
|
||||||
# Target server after logout
|
|
||||||
send_after_logout:
|
|
||||||
enabled: false
|
|
||||||
message: ''
|
|
||||||
delay: 5
|
|
||||||
# Server name ("ServerName") or group ("G:GroupName")
|
|
||||||
# Groups are avariable only when the bungeecord module is avariable.
|
|
||||||
# If the server change fails the player will be kicked.
|
|
||||||
target: LoginLobby1
|
|
||||||
failKickMessage: 'Failed to connect to the lobby! Please try to join the server again!'
|
|
||||||
|
|
||||||
# Variables:
|
|
||||||
# %p playername
|
|
||||||
bungee_commands:
|
|
||||||
player_command_after_register:
|
|
||||||
enabled: false
|
|
||||||
cmd: ''
|
|
||||||
console_command_after_register:
|
|
||||||
enabled: false
|
|
||||||
cmd: 'alert %p joined for the first time the network!'
|
|
||||||
player_command_after_login:
|
|
||||||
enabled: false
|
|
||||||
cmd: 'glist'
|
|
||||||
console_command_after_login:
|
|
||||||
enabled: false
|
|
||||||
cmd: 'alert %p logged in correctly!'
|
|
||||||
player_command_after_join:
|
|
||||||
enabled: false
|
|
||||||
cmd: ''
|
|
||||||
console_command_after_join:
|
|
||||||
enabled: false
|
|
||||||
cmd: 'alert %p joined the network!'
|
|
||||||
player_command_first_join:
|
|
||||||
enabled: false
|
|
||||||
cmd: ''
|
|
||||||
console_command_first_join:
|
|
||||||
enabled: false
|
|
||||||
cmd: 'alert %p joined for the first time the network!'
|
|
||||||
|
|
||||||
# ===========================
|
|
||||||
# Sessions configuration.
|
|
||||||
# ===========================
|
|
||||||
|
|
||||||
sessions:
|
|
||||||
# Enable sessions.
|
|
||||||
# When a player is authenticated, his IP and his nickname is saved.
|
|
||||||
# The next time the player will join the server, if his IP is the same
|
|
||||||
# of the last time, and the timeout time hasn't expired, he will be
|
|
||||||
# automatically authenticated.
|
|
||||||
enabled: false
|
|
||||||
# Session timeout.
|
|
||||||
# 0 for unlimited time (Very dangerous, use it at your own risk!)
|
|
||||||
# Consider that if player's ip has changed but the timeout hasn't
|
|
||||||
# expired, player will be kicked out of the sever!
|
|
||||||
timeout: 10
|
|
||||||
# When enabled a player's session will expire if someone tries to
|
|
||||||
# login with a different IP Address.
|
|
||||||
expire_on_ip_change: true
|
|
||||||
|
|
||||||
# ===========================
|
|
||||||
# Registration settings.
|
|
||||||
# ===========================
|
|
||||||
|
|
||||||
registration:
|
|
||||||
# After how many time unregistered players should be kicked?
|
|
||||||
# Set to 0 to disable. (default: 30)
|
|
||||||
timeout: 30
|
|
||||||
|
|
||||||
nickname:
|
|
||||||
min_length: 4
|
|
||||||
max_lenght: 16
|
|
||||||
# Regex syntax.
|
|
||||||
allowed_characters: '[a-zA-Z0-9_]*'
|
|
||||||
|
|
||||||
password:
|
|
||||||
# Enable double check of password on registration:
|
|
||||||
# /register <password> <confirmPassword>
|
|
||||||
double_check: true
|
|
||||||
# Minimum password lenght.
|
|
||||||
min_length: 5
|
|
||||||
# Regex syntax.
|
|
||||||
allowed_characters: '[\x21-\x7E]*'
|
|
||||||
# Denied unsafe passwords.
|
|
||||||
unsafePasswords:
|
|
||||||
- '123456'
|
|
||||||
- 'password'
|
|
||||||
- 'qwerty'
|
|
||||||
- '12345'
|
|
||||||
- '54321'
|
|
||||||
|
|
||||||
# ===========================
|
|
||||||
# Login settings.
|
|
||||||
# ===========================
|
|
||||||
|
|
||||||
login:
|
|
||||||
# After how many time unlogged players should be kicked?
|
|
||||||
# Set to 0 to disable. (default: 30)
|
|
||||||
timeout: 30
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ===========================
|
|
||||||
# Encryption parameters.
|
|
||||||
# ===========================
|
|
||||||
|
|
||||||
password_encryption:
|
|
||||||
# The hashing algorithm.
|
|
||||||
# Possible values: MD5, SHA1, SHA256, WHIRLPOOL, XAUTH, MD5VB, PHPBB, MYBB, IPB3,
|
|
||||||
# PHPFUSION, SMF, XENFORO, SALTED2MD5, JOOMLA, BCRYPT, WBB3, SHA512, DOUBLEMD5,
|
|
||||||
# PBKDF2, PBKDF2DJANGO, WORDPRESS, ROYALAUTH, CUSTOM (developpers only).
|
|
||||||
encryption_algorithm: SHA256
|
|
||||||
# The salt length for the SALTED2MD5 and MD5(MD5(password)+salt) algorithms.
|
|
||||||
md5_salt_length: 8
|
|
||||||
# If password check fails try all the other hash algorithm.
|
|
||||||
# AuthMe will update the password to the new passwordHash.
|
|
||||||
enable_convertion: false
|
|
||||||
|
|
||||||
# ===========================
|
|
||||||
# Unlogged user restrictions.
|
|
||||||
# ===========================
|
|
||||||
|
|
||||||
unlogged_restrictions:
|
|
||||||
# Deny chat messages send for unlogged users.
|
|
||||||
deny_chat: true
|
|
||||||
# Hide chat to unlogged users.
|
|
||||||
# Only player messages, plugins will be able to send messages to the player anyway.
|
|
||||||
hide_chat: false
|
|
||||||
|
|
||||||
# Deny any command message not in the whitelist below.
|
|
||||||
deny_commands: true
|
|
||||||
command_whitelist:
|
|
||||||
- /login
|
|
||||||
- /register
|
|
||||||
- /l
|
|
||||||
- /reg
|
|
||||||
- /email
|
|
||||||
- /captcha
|
|
||||||
|
|
||||||
movements:
|
|
||||||
# Restrict player movements.
|
|
||||||
restrict: true
|
|
||||||
# Allowed radius.
|
|
||||||
allowed_radius: 0
|
|
||||||
# Should unlogged players have speed = 0?
|
|
||||||
# After the login the walking/flying speeed will be reset to the default value.
|
|
||||||
removeSpeed: true
|
|
||||||
|
|
||||||
# End is there atm xD
|
|
||||||
|
|
||||||
# This option will save the quit location of the players.
|
|
||||||
SaveQuitLocation: false
|
|
||||||
# Should not logged in players be teleported to the spawn?
|
|
||||||
# After the authentication, if SaveQuitLocation is enabled,
|
|
||||||
# they will be teleported back to their normal position.
|
|
||||||
teleportUnAuthedToSpawn: false
|
|
||||||
|
|
||||||
# If enabled, after the login, if the ForceSpawnOnTheseWorlds setting contains
|
|
||||||
# the player's world, he will be teleported to the world spawnpoint.
|
|
||||||
# The quit location of the player will be overwritten.
|
|
||||||
# This is different from "teleportUnAuthedToSpawn" that teleports player
|
|
||||||
# back to his quit location after the authentication.
|
|
||||||
ForceSpawnLocOnJoinEnabled: false
|
|
||||||
# WorldNames where we need to force the spawn location
|
|
||||||
# Warning: This setting is Case Sensitive!
|
|
||||||
ForceSpawnOnTheseWorlds:
|
|
||||||
- world
|
|
||||||
- world_nether
|
|
||||||
- world_the_end
|
|
||||||
|
|
||||||
# this is very important options,
|
|
||||||
# every time player join the server,
|
|
||||||
# if they are registered, AuthMe will switch him
|
|
||||||
# to unLoggedInGroup, this
|
|
||||||
# should prevent all major exploit.
|
|
||||||
# So you can set up on your Permission Plugin
|
|
||||||
# this special group with 0 permissions, or permissions to chat,
|
|
||||||
# or permission to
|
|
||||||
# send private message or all other perms that you want,
|
|
||||||
# the better way is to set up
|
|
||||||
# this group with few permissions,
|
|
||||||
# so if player try to exploit some account,
|
|
||||||
# they can
|
|
||||||
# do anything except what you set in perm Group.
|
|
||||||
# After a correct logged-in player will be
|
|
||||||
# moved to his correct permissions group!
|
|
||||||
# Pay attention group name is case sensitive,
|
|
||||||
# so Admin is different from admin,
|
|
||||||
# otherwise your group will be wiped,
|
|
||||||
# and player join in default group []!
|
|
||||||
# Example unLoggedinGroup: NotLogged
|
|
||||||
unLoggedinGroup: unLoggedinGroup
|
|
||||||
|
|
||||||
# ===========================
|
|
||||||
# Address restrictions
|
|
||||||
# ===========================
|
|
||||||
|
|
||||||
# Max number of registrations per IP (default: 1)
|
|
||||||
maxRegPerIp: 1
|
|
||||||
# Maximum allowed number of Logins per IP, 0 to disable (default: 0)
|
|
||||||
maxLoginPerIp: 0
|
|
||||||
# Maximum allowed number of Joins per IP, 0 to disable (default: 0)
|
|
||||||
maxJoinPerIp: 0
|
|
||||||
|
|
||||||
# When this setting is enabled, online players can't be kicked out
|
|
||||||
# due to "Logged in from another Location"
|
|
||||||
# This setting will prevent potential security exploits.
|
|
||||||
ForceSingleSession: true
|
|
||||||
|
|
||||||
# To activate the restricted user feature you need
|
|
||||||
# to enable this option and configure the
|
|
||||||
# AllowedRestrictedUser field.
|
|
||||||
AllowRestrictedUser: false
|
|
||||||
# The restricted user feature will kick players listed below
|
|
||||||
# if they dont match of the defined ip address.
|
|
||||||
# Example:
|
|
||||||
# AllowedRestrictedUser:
|
|
||||||
# - playername;127.0.0.1
|
|
||||||
AllowedRestrictedUser:
|
|
||||||
- playername;127.0.0.
|
|
||||||
# Ban ip when the ip is not the ip registered in database
|
|
||||||
banUnsafedIP: false
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ===============================
|
|
||||||
# Other restrictions
|
|
||||||
# ===============================
|
|
||||||
|
|
||||||
# Should we protect the player inventory before logging in?
|
|
||||||
# Warning: Requires the latest version of ProtocolLib!
|
|
||||||
ProtectInventoryBeforeLogIn: true
|
|
||||||
|
|
||||||
# Should unregistered players be kicked immediately?
|
|
||||||
kickNonRegistered: false
|
|
||||||
# Should players be kicked on wrong password?
|
|
||||||
kickOnWrongPassword: false
|
|
||||||
|
|
||||||
# Should we display all other accounts of a player when he joins?
|
|
||||||
# Required permission: authme.admin.accounts
|
|
||||||
displayOtherAccounts: true
|
|
||||||
|
|
||||||
# ===============================
|
|
||||||
# Restrictions compatibility
|
|
||||||
# ===============================
|
|
||||||
|
|
||||||
# Spawn Priority. Avariable values : authme, essentials, multiverse, default
|
|
||||||
spawnPriority: authme,essentials,multiverse,default
|
|
||||||
# AuthMe will NEVER teleport players!
|
|
||||||
noTeleport: false
|
|
||||||
|
|
||||||
GameMode:
|
|
||||||
# Do you want to set player's gamemode to survival when he joins?
|
|
||||||
# This enables also the settings below.
|
|
||||||
ForceSurvivalMode: false
|
|
||||||
# Do you want to reset player's inventory if player joins with creative mode?
|
|
||||||
ResetInventoryIfCreative: false
|
|
||||||
# Do you want to force the survival mode ONLY after the /login process?
|
|
||||||
ForceOnlyAfterLogin: false
|
|
||||||
|
|
||||||
# sgdc3: Ok, our configuration is shit.... xD Today I will stop there
|
|
||||||
|
|
||||||
|
|
||||||
registration:
|
|
||||||
# enable registration on the server?
|
|
||||||
enabled: true
|
|
||||||
# Send every X seconds a message to a player to
|
|
||||||
# remind him that he has to login/register
|
|
||||||
messageInterval: 5
|
|
||||||
# Only registered and logged in players can play.
|
|
||||||
# See restrictions for exceptions
|
|
||||||
force: true
|
|
||||||
# Does we replace password registration by an Email registration method ?
|
|
||||||
enableEmailRegistrationSystem: false
|
|
||||||
# Enable double check of email when you register
|
|
||||||
# when it's true, registration require that kind of command:
|
|
||||||
# /register <email> <confirmEmail>
|
|
||||||
doubleEmailCheck: false
|
|
||||||
# Do we force kicking player after a successful registration ?
|
|
||||||
# Do not use with login feature below
|
|
||||||
forceKickAfterRegister: false
|
|
||||||
# Does AuthMe need to enforce a /login after a successful registration ?
|
|
||||||
forceLoginAfterRegister: false
|
|
||||||
unrestrictions:
|
|
||||||
# below you can list all your account name, that
|
|
||||||
# AuthMe will ignore for registration or login, configure it
|
|
||||||
# at your own risk!! Remember that if you are going to add
|
|
||||||
# nickname with [], you have to delimit name with ' '.
|
|
||||||
# this option add compatibility with BuildCraft and some
|
|
||||||
# other mods.
|
|
||||||
# It is CaseSensitive!
|
|
||||||
UnrestrictedName: []
|
|
||||||
# Message language, available : en, de, br, cz, pl, fr, ru, hu, sk, es, zhtw, fi, zhcn, lt, it, ko, pt
|
|
||||||
messagesLanguage: en
|
|
||||||
# Force these commands after /login, without any '/', use %p for replace with player name
|
|
||||||
forceCommands: []
|
|
||||||
# Force these commands after /login as a server console, without any '/', use %p for replace with player name
|
|
||||||
forceCommandsAsConsole: []
|
|
||||||
# Force these commands after /register, without any '/', use %p for replace with player name
|
|
||||||
forceRegisterCommands: []
|
|
||||||
# Force these commands after /register as a server console, without any '/', use %p for replace with player name
|
|
||||||
forceRegisterCommandsAsConsole: []
|
|
||||||
# Do we need to broadcast the welcome message to all server or only to the player? set true for server or false for player
|
|
||||||
broadcastWelcomeMessage: false
|
|
||||||
# Do we need to delay the join/leave message to be displayed only when the player is authenticated ?
|
|
||||||
delayJoinMessage: false
|
|
||||||
removeJoinMessage: false
|
|
||||||
removeLeaveMessage: false
|
|
||||||
# Do we need to add potion effect Blinding before login/register ?
|
|
||||||
applyBlindEffect: false
|
|
||||||
ExternalBoardOptions:
|
|
||||||
# MySQL column for the salt , needed for some forum/cms support
|
|
||||||
mySQLColumnSalt: ''
|
|
||||||
# MySQL column for the group, needed for some forum/cms support
|
|
||||||
mySQLColumnGroup: ''
|
|
||||||
# -1 mean disabled. If u want that only
|
|
||||||
# activated player can login in your server
|
|
||||||
# u can put in this options the group number
|
|
||||||
# of unactivated user, needed for some forum/cms support
|
|
||||||
nonActivedUserGroup: -1
|
|
||||||
# Other MySQL columns where we need to put the Username (case sensitive)
|
|
||||||
mySQLOtherUsernameColumns: []
|
|
||||||
# How much Log to Round needed in BCrypt(do not change it if you do not know what's your doing)
|
|
||||||
bCryptLog2Round: 10
|
|
||||||
# phpBB prefix defined during phpbb installation process
|
|
||||||
phpbbTablePrefix: 'phpbb_'
|
|
||||||
# phpBB activated group id , 2 is default registered group defined by phpbb
|
|
||||||
phpbbActivatedGroupId: 2
|
|
||||||
# WordPress prefix defined during WordPress installation process
|
|
||||||
wordpressTablePrefix: 'wp_'
|
|
||||||
permission:
|
|
||||||
# Take care with this options, if you dont want
|
|
||||||
# to use Vault and Group Switching of
|
|
||||||
# AuthMe for unloggedIn players put true
|
|
||||||
# below, default is false.
|
|
||||||
EnablePermissionCheck: false
|
|
||||||
BackupSystem:
|
|
||||||
# Enable or Disable Automatic Backup
|
|
||||||
ActivateBackup: false
|
|
||||||
# set Backup at every start of Server
|
|
||||||
OnServerStart: false
|
|
||||||
# set Backup at every stop of Server
|
|
||||||
OnServerStop: true
|
|
||||||
# Windows only mysql installation Path
|
|
||||||
MysqlWindowsPath: 'C:\\Program Files\\MySQL\\MySQL Server 5.1\\'
|
|
||||||
Security:
|
|
||||||
SQLProblem:
|
|
||||||
# Stop the server if we can't contact the sql database
|
|
||||||
# Take care with this, if you set that to false,
|
|
||||||
# AuthMe automatically disable and the server is not protected!
|
|
||||||
stopServer: true
|
|
||||||
ReloadCommand:
|
|
||||||
# /reload support
|
|
||||||
useReloadCommandSupport: true
|
|
||||||
console:
|
|
||||||
# Remove spam console
|
|
||||||
noConsoleSpam: false
|
|
||||||
captcha:
|
|
||||||
# Player need to put a captcha when he fails too lot the password
|
|
||||||
useCaptcha: false
|
|
||||||
# Max allowed tries before request a captcha
|
|
||||||
maxLoginTry: 5
|
|
||||||
# Captcha length
|
|
||||||
captchaLength: 5
|
|
||||||
Converter:
|
|
||||||
Rakamak:
|
|
||||||
# Rakamak file name
|
|
||||||
fileName: users.rak
|
|
||||||
# Rakamak use ip ?
|
|
||||||
useIP: false
|
|
||||||
# IP file name for rakamak
|
|
||||||
ipFileName: UsersIp.rak
|
|
||||||
CrazyLogin:
|
|
||||||
# CrazyLogin database file
|
|
||||||
fileName: accounts.db
|
|
||||||
Email:
|
|
||||||
# Email SMTP server host
|
|
||||||
mailSMTP: smtp.gmail.com
|
|
||||||
# Email SMTP server port
|
|
||||||
mailPort: 465
|
|
||||||
# Email account that send the mail
|
|
||||||
mailAccount: ''
|
|
||||||
# Email account password
|
|
||||||
mailPassword: ''
|
|
||||||
# Custom SenderName, that replace the mailAccount name in the email
|
|
||||||
mailSenderName: ''
|
|
||||||
# Random password length
|
|
||||||
RecoveryPasswordLength: 8
|
|
||||||
# Email subject of password get
|
|
||||||
mailSubject: 'Your new AuthMe Password'
|
|
||||||
# Email text here
|
|
||||||
mailText: 'Dear <playername>, <br /><br /> This is your new AuthMe password for the server <br /><br /> <servername> : <br /><br /> <generatedpass><br /><br />Do not forget to change password after login! <br /> /changepassword <generatedpass> newPassword'
|
|
||||||
# Like maxRegPerIp but with email
|
|
||||||
maxRegPerEmail: 1
|
|
||||||
# Recall players to add an email ?
|
|
||||||
recallPlayers: false
|
|
||||||
# Delay in minute for the recall scheduler
|
|
||||||
delayRecall: 5
|
|
||||||
# Blacklist these domains for emails
|
|
||||||
emailBlacklisted:
|
|
||||||
- 10minutemail.com
|
|
||||||
# WhiteList only these domains for emails
|
|
||||||
emailWhitelisted: []
|
|
||||||
# Do we need to send new password draw in an image ?
|
|
||||||
generateImage: false
|
|
||||||
Hooks:
|
|
||||||
# Do we need to hook with multiverse for spawn checking?
|
|
||||||
multiverse: true
|
|
||||||
# Do we need to hook with BungeeCord for get the real Player ip ?
|
|
||||||
bungeecord: false
|
|
||||||
# Do we need to disable Essentials SocialSpy on join ?
|
|
||||||
disableSocialSpy: true
|
|
||||||
# Do we need to force /motd Essentials command on join ?
|
|
||||||
useEssentialsMotd: false
|
|
||||||
# Do we need to cache custom Attributes ?
|
|
||||||
customAttributes: false
|
|
||||||
Purge:
|
|
||||||
# On Enable , does AuthMe need to purge automatically old accounts unused ?
|
|
||||||
useAutoPurge: false
|
|
||||||
# Number of Days an account become Unused
|
|
||||||
daysBeforeRemovePlayer: 60
|
|
||||||
# Do we need to remove the player.dat file during purge process ?
|
|
||||||
removePlayerDat: false
|
|
||||||
# Do we need to remove the Essentials/users/player.yml file during purge process ?
|
|
||||||
removeEssentialsFile: false
|
|
||||||
# World where are players.dat stores
|
|
||||||
defaultWorld: 'world'
|
|
||||||
# Do we need to remove LimitedCreative/inventories/player.yml , player_creative.yml files during purge process ?
|
|
||||||
removeLimitedCreativesInventories: false
|
|
||||||
# Do we need to remove the AntiXRayData/PlayerData/player file during purge process ?
|
|
||||||
removeAntiXRayFile: false
|
|
||||||
# Do we need to remove permissions ?
|
|
||||||
removePermissions: false
|
|
||||||
Protection:
|
|
||||||
# Enable some servers protection ( country based login, antibot )
|
|
||||||
enableProtection: false
|
|
||||||
# Countries allowed to join the server and register, see http://dev.bukkit.org/bukkit-plugins/authme-reloaded/pages/countries-codes/ for countries' codes
|
|
||||||
countries:
|
|
||||||
- US
|
|
||||||
- GB
|
|
||||||
# Countries blacklisted automatically ( without any needed to enable protection )
|
|
||||||
countriesBlacklist:
|
|
||||||
- A1
|
|
||||||
# Do we need to enable automatic antibot system?
|
|
||||||
enableAntiBot: false
|
|
||||||
# Max number of player allowed to login in 5 secs before enable AntiBot system automatically
|
|
||||||
antiBotSensibility: 5
|
|
||||||
# Duration in minutes of the antibot automatic system
|
|
||||||
antiBotDuration: 10
|
|
||||||
VeryGames:
|
|
||||||
# These features are only available on VeryGames Server Provider
|
|
||||||
enableIpCheck: false
|
|
||||||
@@ -1,199 +0,0 @@
|
|||||||
name: ${pluginName}
|
|
||||||
authors: [${pluginAuthors}]
|
|
||||||
website: ${project.url}
|
|
||||||
description: ${project.description}
|
|
||||||
main: ${mainClass}
|
|
||||||
version: ${project.version}-b${buildNumber}
|
|
||||||
softdepend:
|
|
||||||
- Vault
|
|
||||||
- PermissionsBukkit
|
|
||||||
- PermissionsEX
|
|
||||||
- EssentialsGroupManager
|
|
||||||
- Multiverse-Core
|
|
||||||
- Essentials
|
|
||||||
- EssentialsSpawn
|
|
||||||
- ProtocolLib
|
|
||||||
commands:
|
|
||||||
authme:
|
|
||||||
description: AuthMe admin commands
|
|
||||||
usage: '/authme reload|register playername password|changepassword playername password|unregister playername|version|converter datatype'
|
|
||||||
permission: authme.admin
|
|
||||||
register:
|
|
||||||
description: Register an account
|
|
||||||
usage: /register password confirmpassword
|
|
||||||
aliases: [reg]
|
|
||||||
permission: authme.player.register
|
|
||||||
login:
|
|
||||||
description: Login into a account
|
|
||||||
usage: /login password
|
|
||||||
aliases: [l,log]
|
|
||||||
permission: authme.player.login
|
|
||||||
changepassword:
|
|
||||||
description: Change password of a account
|
|
||||||
usage: /changepassword oldPassword newPassword
|
|
||||||
permission: authme.player.changepassword
|
|
||||||
logout:
|
|
||||||
description: Logout from the server
|
|
||||||
usage: /logout
|
|
||||||
permission: authme.player.logout
|
|
||||||
unregister:
|
|
||||||
description: unregister your account
|
|
||||||
usage: /unregister password
|
|
||||||
permission: authme.player.unregister
|
|
||||||
email:
|
|
||||||
description: Add Email or recover password
|
|
||||||
usage: '/email add your@email.com your@email.com|change oldEmail newEmail|recovery your@email.com'
|
|
||||||
permission: authme.player.email
|
|
||||||
captcha:
|
|
||||||
description: Captcha command
|
|
||||||
usage: /captcha theCaptcha
|
|
||||||
permission: authme.player.captcha
|
|
||||||
permissions:
|
|
||||||
authme.canbeforced:
|
|
||||||
description: Allow the user to be forced-logged via API
|
|
||||||
default: true
|
|
||||||
authme.player:
|
|
||||||
description: Gives access to all authme player commands
|
|
||||||
default: true
|
|
||||||
children:
|
|
||||||
authme.player.login: true
|
|
||||||
authme.player.logout: true
|
|
||||||
authme.player.register: true
|
|
||||||
authme.player.unregister: true
|
|
||||||
authme.player.changepassword: true
|
|
||||||
authme.player.captcha: true
|
|
||||||
authme.player.email: true
|
|
||||||
authme.player.register:
|
|
||||||
description: Register your account
|
|
||||||
default: false
|
|
||||||
authme.player.unregister:
|
|
||||||
description: Unregister your account
|
|
||||||
default: false
|
|
||||||
authme.player.login:
|
|
||||||
description: Login into your account
|
|
||||||
default: false
|
|
||||||
authme.player.logout:
|
|
||||||
description: Logout from your account
|
|
||||||
default: false
|
|
||||||
authme.player.changepassword:
|
|
||||||
description: Change password of your account
|
|
||||||
default: false
|
|
||||||
authme.player.email:
|
|
||||||
description: Gives access to player's email commands
|
|
||||||
default: false
|
|
||||||
children:
|
|
||||||
authme.player.email.add: true
|
|
||||||
authme.player.email.change: true
|
|
||||||
authme.player.email.recover: true
|
|
||||||
authme.player.email.add:
|
|
||||||
description: Add an email to your account
|
|
||||||
default: false
|
|
||||||
authme.player.email.change:
|
|
||||||
description: Change email of your account
|
|
||||||
default: false
|
|
||||||
authme.player.email.recover:
|
|
||||||
description: Recover your account
|
|
||||||
default: false
|
|
||||||
authme.player.captcha:
|
|
||||||
description: Captcha command
|
|
||||||
default: false
|
|
||||||
authme.admin:
|
|
||||||
description: Gives access to all authme admin commands
|
|
||||||
default: op
|
|
||||||
children:
|
|
||||||
authme.admin.forcelogin: true
|
|
||||||
authme.admin.forcelogout: true
|
|
||||||
authme.admin.register: true
|
|
||||||
authme.admin.unregister: true
|
|
||||||
authme.admin.changemail: true
|
|
||||||
authme.admin.changepassword: true
|
|
||||||
authme.admin.lastlogin: true
|
|
||||||
authme.admin.accounts: true
|
|
||||||
authme.admin.getemail: true
|
|
||||||
authme.admin.getip: true
|
|
||||||
authme.admin.setspawn: true
|
|
||||||
authme.admin.spawn: true
|
|
||||||
authme.admin.setfirstspawn: true
|
|
||||||
authme.admin.firstspawn: true
|
|
||||||
authme.admin.purge: true
|
|
||||||
authme.admin.purgebannedplayers: true
|
|
||||||
authme.admin.purgelastpos: true
|
|
||||||
authme.admin.converter: true
|
|
||||||
authme.admin.reload: true
|
|
||||||
authme.admin.switchantibot: true
|
|
||||||
authme.admin.seeotheraccounts: true
|
|
||||||
authme.admin.register:
|
|
||||||
description: Register an account
|
|
||||||
default: false
|
|
||||||
authme.admin.unregister:
|
|
||||||
description: Unregister an account
|
|
||||||
default: false
|
|
||||||
authme.admin.forcelogin:
|
|
||||||
description: Force login for that player
|
|
||||||
default: false
|
|
||||||
authme.admin.forcelogout:
|
|
||||||
description: Force logout for that player
|
|
||||||
default: false
|
|
||||||
authme.admin.changepassword:
|
|
||||||
description: Change the password of an account
|
|
||||||
default: false
|
|
||||||
authme.admin.getemail:
|
|
||||||
description: Get last email about a player
|
|
||||||
default: false
|
|
||||||
authme.admin.changeemail:
|
|
||||||
description: Change a player email
|
|
||||||
default: false
|
|
||||||
authme.admin.accounts:
|
|
||||||
description: Display Players Accounts
|
|
||||||
default: false
|
|
||||||
authme.admin.seeotheraccounts:
|
|
||||||
description: Display other accounts about a player when he logs in
|
|
||||||
default: false
|
|
||||||
authme.admin.lastlogin:
|
|
||||||
description: Get last login date about a player
|
|
||||||
default: false
|
|
||||||
authme.admin.getip:
|
|
||||||
description: Get IP from a player (fake and real)
|
|
||||||
default: false
|
|
||||||
authme.admin.setspawn:
|
|
||||||
description: Set the AuthMe spawn point
|
|
||||||
default: false
|
|
||||||
authme.admin.spawn:
|
|
||||||
description: Teleport to AuthMe spawn point
|
|
||||||
default: false
|
|
||||||
authme.admin.setfirstspawn:
|
|
||||||
description: Set the AuthMe First Spawn Point
|
|
||||||
default: false
|
|
||||||
authme.admin.firstspawn:
|
|
||||||
description: Teleport to AuthMe First Spawn Point
|
|
||||||
default: false
|
|
||||||
authme.admin.switchantibot:
|
|
||||||
description: Switch AntiBot mode on/off
|
|
||||||
default: false
|
|
||||||
authme.admin.purge:
|
|
||||||
description: Database purge command
|
|
||||||
default: false
|
|
||||||
authme.admin.purgebannedplayers:
|
|
||||||
description: Purge banned players
|
|
||||||
default: false
|
|
||||||
authme.admin.purgelastpos:
|
|
||||||
description: Purge last position of a player/players
|
|
||||||
default: false
|
|
||||||
authme.admin.converter:
|
|
||||||
description: Allow the /authme converter command
|
|
||||||
default: false
|
|
||||||
authme.admin.reload:
|
|
||||||
description: Reload the plugin
|
|
||||||
default: false
|
|
||||||
authme.vip:
|
|
||||||
description: Allow vip slot when the server is full
|
|
||||||
default: false
|
|
||||||
authme.bypassantibot:
|
|
||||||
description: Bypass the AntiBot check
|
|
||||||
default: false
|
|
||||||
authme.allowmultipleaccounts:
|
|
||||||
description: Allow more accounts for same ip
|
|
||||||
default: false
|
|
||||||
authme.bypassforcesurvival:
|
|
||||||
description: Bypass all ForceSurvival features
|
|
||||||
default: false
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -1,148 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*****************************************************************************
|
|
||||||
* AuthMe website integration logic *
|
|
||||||
* ------------------------------------------------------------------------- *
|
|
||||||
* Allows interaction with the AuthMe database (registration, password *
|
|
||||||
* verification). Don't forget to update the AUTHME_TABLE value and your *
|
|
||||||
* database credentials in getAuthmeMySqli(). *
|
|
||||||
* *
|
|
||||||
* Source: https://github.com/AuthMe/AuthMeReloaded/ *
|
|
||||||
*****************************************************************************/
|
|
||||||
abstract class AuthMeController {
|
|
||||||
|
|
||||||
const AUTHME_TABLE = 'authme';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Entry point function to check supplied credentials against the AuthMe database.
|
|
||||||
*
|
|
||||||
* @param string $username the username
|
|
||||||
* @param string $password the password
|
|
||||||
* @return bool true iff the data is correct, false otherwise
|
|
||||||
*/
|
|
||||||
function checkPassword($username, $password) {
|
|
||||||
if (is_scalar($username) && is_scalar($password)) {
|
|
||||||
$hash = $this->getHashFromDatabase($username);
|
|
||||||
if ($hash) {
|
|
||||||
return $this->isValidPassword($password, $hash);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether the user exists in the database or not.
|
|
||||||
*
|
|
||||||
* @param string $username the username to check
|
|
||||||
* @return bool true if the user exists; false otherwise
|
|
||||||
*/
|
|
||||||
function isUserRegistered($username) {
|
|
||||||
$mysqli = $this->getAuthmeMySqli();
|
|
||||||
if ($mysqli !== null) {
|
|
||||||
$stmt = $mysqli->prepare('SELECT 1 FROM ' . self::AUTHME_TABLE . ' WHERE username = ?');
|
|
||||||
$stmt->bind_param('s', $username);
|
|
||||||
$stmt->execute();
|
|
||||||
return $stmt->fetch();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Defensive default to true; we actually don't know
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers a player with the given username.
|
|
||||||
*
|
|
||||||
* @param string $username the username to register
|
|
||||||
* @param string $password the password to associate to the user
|
|
||||||
* @param string $email the email (may be empty)
|
|
||||||
* @return bool whether or not the registration was successful
|
|
||||||
*/
|
|
||||||
function register($username, $password, $email) {
|
|
||||||
$email = $email ? $email : 'your@email.com';
|
|
||||||
$mysqli = $this->getAuthmeMySqli();
|
|
||||||
if ($mysqli !== null) {
|
|
||||||
$hash = $this->hash($password);
|
|
||||||
$stmt = $mysqli->prepare('INSERT INTO ' . self::AUTHME_TABLE . ' (username, realname, password, email, ip) '
|
|
||||||
. 'VALUES (?, ?, ?, ?, ?)');
|
|
||||||
$username_low = strtolower($username);
|
|
||||||
$stmt->bind_param('sssss', $username_low, $username, $hash, $email, $_SERVER['REMOTE_ADDR']);
|
|
||||||
return $stmt->execute();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Changes password for player.
|
|
||||||
*
|
|
||||||
* @param string $username the username
|
|
||||||
* @param string $password the password
|
|
||||||
* @return bool true whether or not password change was successful
|
|
||||||
*/
|
|
||||||
function changePassword($username, $password) {
|
|
||||||
$mysqli = $this->getAuthmeMySqli();
|
|
||||||
if ($mysqli !== null) {
|
|
||||||
$hash = $this->hash($password);
|
|
||||||
$stmt = $mysqli->prepare('UPDATE ' . self::AUTHME_TABLE . ' SET password=? '
|
|
||||||
. 'WHERE username=?');
|
|
||||||
$username_low = strtolower($username);
|
|
||||||
$stmt->bind_param('ss', $hash, $username_low);
|
|
||||||
return $stmt->execute();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hashes the given password.
|
|
||||||
*
|
|
||||||
* @param $password string the clear-text password to hash
|
|
||||||
* @return string the resulting hash
|
|
||||||
*/
|
|
||||||
protected abstract function hash($password);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks whether the given password matches the hash.
|
|
||||||
*
|
|
||||||
* @param $password string the clear-text password
|
|
||||||
* @param $hash string the password hash
|
|
||||||
* @return boolean true if the password matches, false otherwise
|
|
||||||
*/
|
|
||||||
protected abstract function isValidPassword($password, $hash);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a connection to the database.
|
|
||||||
*
|
|
||||||
* @return mysqli|null the mysqli object or null upon error
|
|
||||||
*/
|
|
||||||
private function getAuthmeMySqli() {
|
|
||||||
// CHANGE YOUR DATABASE DETAILS HERE BELOW: host, user, password, database name
|
|
||||||
$mysqli = new mysqli('localhost', 'root', '', 'authme');
|
|
||||||
if (mysqli_connect_error()) {
|
|
||||||
printf('Could not connect to AuthMe database. Errno: %d, error: "%s"',
|
|
||||||
mysqli_connect_errno(), mysqli_connect_error());
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return $mysqli;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the hash associated with the given user from the database.
|
|
||||||
*
|
|
||||||
* @param string $username the username whose hash should be retrieved
|
|
||||||
* @return string|null the hash, or null if unavailable (e.g. username doesn't exist)
|
|
||||||
*/
|
|
||||||
private function getHashFromDatabase($username) {
|
|
||||||
$mysqli = $this->getAuthmeMySqli();
|
|
||||||
if ($mysqli !== null) {
|
|
||||||
$stmt = $mysqli->prepare('SELECT password FROM ' . self::AUTHME_TABLE . ' WHERE username = ?');
|
|
||||||
$stmt->bind_param('s', $username);
|
|
||||||
$stmt->execute();
|
|
||||||
$stmt->bind_result($password);
|
|
||||||
if ($stmt->fetch()) {
|
|
||||||
return $password;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/***********************************************************
|
|
||||||
* AuthMe website integration logic for BCrypt *
|
|
||||||
* ------------------------------------------------------- *
|
|
||||||
* See AuthMeController for details. *
|
|
||||||
* *
|
|
||||||
* Source: https://github.com/AuthMe/AuthMeReloaded/ *
|
|
||||||
***********************************************************/
|
|
||||||
class Bcrypt extends AuthMeController {
|
|
||||||
|
|
||||||
protected function hash($password) {
|
|
||||||
return password_hash($password, PASSWORD_BCRYPT);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function isValidPassword($password, $hash) {
|
|
||||||
return password_verify($password, $hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/***********************************************************
|
|
||||||
* AuthMe website integration logic for PBKDF2 *
|
|
||||||
* ------------------------------------------------------- *
|
|
||||||
* See AuthMeController for details. *
|
|
||||||
* *
|
|
||||||
* Source: https://github.com/AuthMe/AuthMeReloaded/ *
|
|
||||||
***********************************************************/
|
|
||||||
class Pbkdf2 extends AuthMeController {
|
|
||||||
|
|
||||||
/** @var string[] range of characters for salt generation */
|
|
||||||
private $CHARS;
|
|
||||||
|
|
||||||
const SALT_LENGTH = 16;
|
|
||||||
const NUMBER_OF_ITERATIONS = 10000;
|
|
||||||
|
|
||||||
public function __construct() {
|
|
||||||
$this->CHARS = self::initCharRange();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function isValidPassword($password, $hash) {
|
|
||||||
// hash := pbkdf2_sha256$iterations$salt$hash
|
|
||||||
$parts = explode('$', $hash);
|
|
||||||
return count($parts) === 4 && $hash === $this->computeHash($parts[1], $parts[2], $password);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function hash($password) {
|
|
||||||
$salt = $this->generateSalt();
|
|
||||||
return $this->computeHash(self::NUMBER_OF_ITERATIONS, $salt, $password);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function computeHash($iterations, $salt, $password) {
|
|
||||||
return 'pbkdf2_sha256$' . self::NUMBER_OF_ITERATIONS . '$' . $salt
|
|
||||||
. '$' . hash_pbkdf2('sha256', $password, $salt, self::NUMBER_OF_ITERATIONS, 64, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string randomly generated salt
|
|
||||||
*/
|
|
||||||
private function generateSalt() {
|
|
||||||
$maxCharIndex = count($this->CHARS) - 1;
|
|
||||||
$salt = '';
|
|
||||||
for ($i = 0; $i < self::SALT_LENGTH; ++$i) {
|
|
||||||
$salt .= $this->CHARS[mt_rand(0, $maxCharIndex)];
|
|
||||||
}
|
|
||||||
return $salt;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static function initCharRange() {
|
|
||||||
return array_merge(range('0', '9'), range('a', 'f'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/***********************************************************
|
|
||||||
* AuthMe website integration logic for SHA256 *
|
|
||||||
* ------------------------------------------------------- *
|
|
||||||
* See AuthMeController for details. *
|
|
||||||
* *
|
|
||||||
* Source: https://github.com/AuthMe/AuthMeReloaded/ *
|
|
||||||
***********************************************************/
|
|
||||||
class Sha256 extends AuthMeController {
|
|
||||||
|
|
||||||
/** @var string[] range of characters for salt generation */
|
|
||||||
private $CHARS;
|
|
||||||
|
|
||||||
const SALT_LENGTH = 16;
|
|
||||||
|
|
||||||
public function __construct() {
|
|
||||||
$this->CHARS = self::initCharRange();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function isValidPassword($password, $hash) {
|
|
||||||
// $SHA$salt$hash, where hash := sha256(sha256(password) . salt)
|
|
||||||
$parts = explode('$', $hash);
|
|
||||||
return count($parts) === 4 && $parts[3] === hash('sha256', hash('sha256', $password) . $parts[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function hash($password) {
|
|
||||||
$salt = $this->generateSalt();
|
|
||||||
return '$SHA$' . $salt . '$' . hash('sha256', hash('sha256', $password) . $salt);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string randomly generated salt
|
|
||||||
*/
|
|
||||||
private function generateSalt() {
|
|
||||||
$maxCharIndex = count($this->CHARS) - 1;
|
|
||||||
$salt = '';
|
|
||||||
for ($i = 0; $i < self::SALT_LENGTH; ++$i) {
|
|
||||||
$salt .= $this->CHARS[mt_rand(0, $maxCharIndex)];
|
|
||||||
}
|
|
||||||
return $salt;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static function initCharRange() {
|
|
||||||
return array_merge(range('0', '9'), range('a', 'f'));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,102 +0,0 @@
|
|||||||
<!--
|
|
||||||
This is a demo page for AuthMe website integration.
|
|
||||||
See AuthMeController.php and the extending classes for the PHP code you need.
|
|
||||||
-->
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<title>AuthMe Integration Sample</title>
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<?php
|
|
||||||
error_reporting(E_ALL);
|
|
||||||
|
|
||||||
require 'AuthMeController.php';
|
|
||||||
|
|
||||||
// Change this to the file of the hash encryption you need, e.g. Bcrypt.php or Sha256.php
|
|
||||||
require 'Sha256.php';
|
|
||||||
// The class name must correspond to the file you have in require above! e.g. require 'Sha256.php'; and new Sha256();
|
|
||||||
$authme_controller = new Sha256();
|
|
||||||
|
|
||||||
$action = get_from_post_or_empty('action');
|
|
||||||
$user = get_from_post_or_empty('username');
|
|
||||||
$pass = get_from_post_or_empty('password');
|
|
||||||
$email = get_from_post_or_empty('email');
|
|
||||||
|
|
||||||
$was_successful = false;
|
|
||||||
if ($action && $user && $pass) {
|
|
||||||
if ($action === 'Log in') {
|
|
||||||
$was_successful = process_login($user, $pass, $authme_controller);
|
|
||||||
} else if ($action === 'Register') {
|
|
||||||
$was_successful = process_register($user, $pass, $email, $authme_controller);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$was_successful) {
|
|
||||||
echo '<h1>Login sample</h1>
|
|
||||||
This is a demo form for AuthMe website integration. Enter your AuthMe login details
|
|
||||||
into the following form to test it.
|
|
||||||
<form method="post">
|
|
||||||
<table>
|
|
||||||
<tr><td>Name</td><td><input type="text" value="' . htmlspecialchars($user) . '" name="username" /></td></tr>
|
|
||||||
<tr><td>Email</td><td><input type="text" value="' . htmlspecialchars($email) . '" name="email" /></td></tr>
|
|
||||||
<tr><td>Pass</td><td><input type="password" value="' . htmlspecialchars($pass) . '" name="password" /></td></tr>
|
|
||||||
<tr>
|
|
||||||
<td><input type="submit" name="action" value="Log in" /></td>
|
|
||||||
<td><input type="submit" name="action" value="Register" /></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</form>';
|
|
||||||
}
|
|
||||||
|
|
||||||
function get_from_post_or_empty($index_name) {
|
|
||||||
return trim(
|
|
||||||
filter_input(INPUT_POST, $index_name, FILTER_UNSAFE_RAW, FILTER_REQUIRE_SCALAR | FILTER_FLAG_STRIP_LOW)
|
|
||||||
?: '');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Login logic
|
|
||||||
function process_login($user, $pass, AuthMeController $controller) {
|
|
||||||
if ($controller->checkPassword($user, $pass)) {
|
|
||||||
printf('<h1>Hello, %s!</h1>', htmlspecialchars($user));
|
|
||||||
echo 'Successful login. Nice to have you back!'
|
|
||||||
. '<br /><a href="index.php">Back to form</a>';
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
echo '<h1>Error</h1> Invalid username or password.';
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register logic
|
|
||||||
function process_register($user, $pass, $email, AuthMeController $controller) {
|
|
||||||
if ($controller->isUserRegistered($user)) {
|
|
||||||
echo '<h1>Error</h1> This user already exists.';
|
|
||||||
} else if (!is_email_valid($email)) {
|
|
||||||
echo '<h1>Error</h1> The supplied email is invalid.';
|
|
||||||
} else {
|
|
||||||
// Note that we don't validate the password or username at all in this demo...
|
|
||||||
$register_success = $controller->register($user, $pass, $email);
|
|
||||||
if ($register_success) {
|
|
||||||
printf('<h1>Welcome, %s!</h1>Thanks for registering', htmlspecialchars($user));
|
|
||||||
echo '<br /><a href="index.php">Back to form</a>';
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
echo '<h1>Error</h1>Unfortunately, there was an error during the registration.';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function is_email_valid($email) {
|
|
||||||
return trim($email) === ''
|
|
||||||
? true // accept no email
|
|
||||||
: filter_var($email, FILTER_VALIDATE_EMAIL);
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
rootProject.name = "AuthMeReReloaded"
|
||||||
@@ -2,37 +2,31 @@ package fr.xephi.authme;
|
|||||||
|
|
||||||
import ch.jalu.injector.Injector;
|
import ch.jalu.injector.Injector;
|
||||||
import ch.jalu.injector.InjectorBuilder;
|
import ch.jalu.injector.InjectorBuilder;
|
||||||
import com.google.gson.annotations.Since;
|
import com.alessiodp.libby.BukkitLibraryManager;
|
||||||
|
import com.github.Anon8281.universalScheduler.UniversalScheduler;
|
||||||
|
import com.github.Anon8281.universalScheduler.scheduling.schedulers.TaskScheduler;
|
||||||
import fr.xephi.authme.api.v3.AuthMeApi;
|
import fr.xephi.authme.api.v3.AuthMeApi;
|
||||||
import fr.xephi.authme.command.CommandArgumentDescription;
|
|
||||||
import fr.xephi.authme.command.CommandHandler;
|
import fr.xephi.authme.command.CommandHandler;
|
||||||
|
import fr.xephi.authme.command.TabCompleteHandler;
|
||||||
import fr.xephi.authme.datasource.DataSource;
|
import fr.xephi.authme.datasource.DataSource;
|
||||||
import fr.xephi.authme.initialization.DataFolder;
|
import fr.xephi.authme.initialization.DataFolder;
|
||||||
import fr.xephi.authme.initialization.DataSourceProvider;
|
import fr.xephi.authme.initialization.DataSourceProvider;
|
||||||
import fr.xephi.authme.initialization.OnShutdownPlayerSaver;
|
import fr.xephi.authme.initialization.OnShutdownPlayerSaver;
|
||||||
import fr.xephi.authme.initialization.OnStartupTasks;
|
import fr.xephi.authme.initialization.OnStartupTasks;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileReader;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.net.HttpURLConnection;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.security.MessageDigest;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import fr.xephi.authme.initialization.SettingsProvider;
|
import fr.xephi.authme.initialization.SettingsProvider;
|
||||||
import fr.xephi.authme.initialization.TaskCloser;
|
import fr.xephi.authme.initialization.TaskCloser;
|
||||||
|
import fr.xephi.authme.listener.AdvancedShulkerFixListener;
|
||||||
|
import fr.xephi.authme.listener.BedrockAutoLoginListener;
|
||||||
import fr.xephi.authme.listener.BlockListener;
|
import fr.xephi.authme.listener.BlockListener;
|
||||||
|
import fr.xephi.authme.listener.DoubleLoginFixListener;
|
||||||
import fr.xephi.authme.listener.EntityListener;
|
import fr.xephi.authme.listener.EntityListener;
|
||||||
|
import fr.xephi.authme.listener.LoginLocationFixListener;
|
||||||
import fr.xephi.authme.listener.PlayerListener;
|
import fr.xephi.authme.listener.PlayerListener;
|
||||||
import fr.xephi.authme.listener.PlayerListener111;
|
import fr.xephi.authme.listener.PlayerListener111;
|
||||||
import fr.xephi.authme.listener.PlayerListener19;
|
import fr.xephi.authme.listener.PlayerListener19;
|
||||||
import fr.xephi.authme.listener.PlayerListener19Spigot;
|
import fr.xephi.authme.listener.PlayerListener19Spigot;
|
||||||
import fr.xephi.authme.listener.PlayerQuitListener;
|
import fr.xephi.authme.listener.PlayerListenerHigherThan18;
|
||||||
import fr.xephi.authme.listener.RegisterListener;
|
import fr.xephi.authme.listener.PurgeListener;
|
||||||
import fr.xephi.authme.listener.ServerListener;
|
import fr.xephi.authme.listener.ServerListener;
|
||||||
import fr.xephi.authme.mail.EmailService;
|
import fr.xephi.authme.mail.EmailService;
|
||||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||||
@@ -41,44 +35,33 @@ import fr.xephi.authme.service.BackupService;
|
|||||||
import fr.xephi.authme.service.BukkitService;
|
import fr.xephi.authme.service.BukkitService;
|
||||||
import fr.xephi.authme.service.MigrationService;
|
import fr.xephi.authme.service.MigrationService;
|
||||||
import fr.xephi.authme.service.bungeecord.BungeeReceiver;
|
import fr.xephi.authme.service.bungeecord.BungeeReceiver;
|
||||||
|
import fr.xephi.authme.service.velocity.VelocityReceiver;
|
||||||
import fr.xephi.authme.service.yaml.YamlParseException;
|
import fr.xephi.authme.service.yaml.YamlParseException;
|
||||||
import fr.xephi.authme.settings.Settings;
|
import fr.xephi.authme.settings.Settings;
|
||||||
import fr.xephi.authme.settings.SettingsWarner;
|
import fr.xephi.authme.settings.SettingsWarner;
|
||||||
import fr.xephi.authme.settings.properties.EmailSettings;
|
import fr.xephi.authme.settings.properties.EmailSettings;
|
||||||
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
import fr.xephi.authme.settings.properties.HooksSettings;
|
||||||
import fr.xephi.authme.settings.properties.SecuritySettings;
|
import fr.xephi.authme.settings.properties.SecuritySettings;
|
||||||
import fr.xephi.authme.task.CleanupTask;
|
import fr.xephi.authme.task.CleanupTask;
|
||||||
|
import fr.xephi.authme.task.Updater;
|
||||||
import fr.xephi.authme.task.purge.PurgeService;
|
import fr.xephi.authme.task.purge.PurgeService;
|
||||||
import fr.xephi.authme.util.ExceptionUtils;
|
import fr.xephi.authme.util.ExceptionUtils;
|
||||||
import fr.xephi.authme.util.TeleportUtils;
|
|
||||||
import org.bstats.bukkit.Metrics;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.Server;
|
import org.bukkit.Server;
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.plugin.Plugin;
|
|
||||||
import org.bukkit.plugin.PluginManager;
|
import org.bukkit.plugin.PluginManager;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
import org.bukkit.scheduler.BukkitScheduler;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import fr.xephi.authme.listener.PlayerQuitListener;
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.MalformedURLException;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Scanner;
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.logging.Level;
|
|
||||||
|
|
||||||
import static fr.xephi.authme.service.BukkitService.TICKS_PER_MINUTE;
|
import static fr.xephi.authme.service.BukkitService.TICKS_PER_MINUTE;
|
||||||
import static fr.xephi.authme.util.Utils.isClassLoaded;
|
import static fr.xephi.authme.util.Utils.isClassLoaded;
|
||||||
import static org.bukkit.Bukkit.getServer;
|
|
||||||
import static org.bukkit.Bukkit.isHardcore;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The AuthMe main class.
|
* The AuthMe main class.
|
||||||
@@ -91,28 +74,37 @@ public class AuthMe extends JavaPlugin {
|
|||||||
private static final int CLEANUP_INTERVAL = 5 * TICKS_PER_MINUTE;
|
private static final int CLEANUP_INTERVAL = 5 * TICKS_PER_MINUTE;
|
||||||
|
|
||||||
// Version and build number values
|
// Version and build number values
|
||||||
private static String pluginVersion = "5.6.0-Fork";
|
private static String pluginVersion = "5.7.0-Fork";
|
||||||
private static final String pluginBuild = "b";
|
private static final String pluginBuild = "b";
|
||||||
private static String pluginBuildNumber = "17";
|
private static String pluginBuildNumber = "53";
|
||||||
protected final Boolean SHAEnabled = false;
|
|
||||||
// Private instances
|
// Private instances
|
||||||
private EmailService emailService;
|
private EmailService emailService;
|
||||||
private CommandHandler commandHandler;
|
private CommandHandler commandHandler;
|
||||||
|
private static TaskScheduler scheduler;
|
||||||
@Inject
|
@Inject
|
||||||
private Settings settings;
|
public static Settings settings;
|
||||||
private DataSource database;
|
private DataSource database;
|
||||||
private BukkitService bukkitService;
|
private BukkitService bukkitService;
|
||||||
private Injector injector;
|
private Injector injector;
|
||||||
private BackupService backupService;
|
private BackupService backupService;
|
||||||
private ConsoleLogger logger;
|
public static ConsoleLogger logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
*/
|
*/
|
||||||
public AuthMe() {
|
public AuthMe() {
|
||||||
}
|
}
|
||||||
public static Boolean SATEnabled = false;
|
|
||||||
public static Boolean GUIEnabled = false;
|
/**
|
||||||
|
* Get the plugin's build
|
||||||
|
*
|
||||||
|
* @return The plugin's build
|
||||||
|
*/
|
||||||
|
public static String getPluginBuild() {
|
||||||
|
return pluginBuild;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the plugin's name.
|
* Get the plugin's name.
|
||||||
*
|
*
|
||||||
@@ -140,34 +132,47 @@ public class AuthMe extends JavaPlugin {
|
|||||||
return pluginBuildNumber;
|
return pluginBuildNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the scheduler
|
||||||
|
*/
|
||||||
|
public static TaskScheduler getScheduler() {
|
||||||
|
return scheduler;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The library manager
|
||||||
|
*/
|
||||||
|
public static BukkitLibraryManager libraryManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method called when the server enables the plugin.
|
* Method called when the server enables the plugin.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
AuthMe.GUIEnabled = false;
|
|
||||||
AuthMe.SATEnabled = false;
|
|
||||||
// Load the plugin version data from the plugin description file
|
// Load the plugin version data from the plugin description file
|
||||||
loadPluginInfo(getDescription().getVersion());
|
loadPluginInfo(getDescription().getVersion());
|
||||||
|
scheduler = UniversalScheduler.getScheduler(this);
|
||||||
|
libraryManager = new BukkitLibraryManager(this);
|
||||||
|
|
||||||
// Set the Logger instance and log file path
|
// Set the Logger instance and log file path
|
||||||
ConsoleLogger.initialize(getLogger(), new File(getDataFolder(), LOG_FILENAME));
|
ConsoleLogger.initialize(getLogger(), new File(getDataFolder(), LOG_FILENAME));
|
||||||
logger = ConsoleLoggerFactory.get(AuthMe.class);
|
logger = ConsoleLoggerFactory.get(AuthMe.class);
|
||||||
logger.info("您正在加载的是由第三方Fork并修复众多错误的 AuthMeReReloaded!");
|
logger.info("You are running an unofficial fork version of AuthMe!");
|
||||||
|
|
||||||
|
|
||||||
// Check server version
|
// Check server version
|
||||||
if (!isClassLoaded("org.spigotmc.event.player.PlayerSpawnLocationEvent")
|
if (!isClassLoaded("org.spigotmc.event.player.PlayerSpawnLocationEvent")
|
||||||
|| !isClassLoaded("org.bukkit.event.player.PlayerInteractAtEntityEvent")) {
|
|| !isClassLoaded("org.bukkit.event.player.PlayerInteractAtEntityEvent")) {
|
||||||
logger.warning("你正在运行不受支持的服务器版本 (" + getServerNameVersionSafe() + "). "
|
logger.warning("You are running an unsupported server version (" + getServerNameVersionSafe() + "). "
|
||||||
+ "AuthMe 仅支持Spigot 1.9及之后的版本!");
|
+ "AuthMe requires Spigot 1.8.X or later!");
|
||||||
stopOrUnload();
|
stopOrUnload();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prevent running AuthMeBridge due to major exploit issues
|
// Prevent running AuthMeBridge due to major exploit issues
|
||||||
if (getServer().getPluginManager().isPluginEnabled("AuthMeBridge")) {
|
if (getServer().getPluginManager().isPluginEnabled("AuthMeBridge")) {
|
||||||
logger.warning("检测到 AuthMeBridge被加载, 对AuthMeBridge的支持已经停止 "
|
logger.warning("Detected AuthMeBridge, support for it has been dropped as it was "
|
||||||
+ "且可能会造成严重漏洞! 已中止加载!");
|
+ "causing exploit issues, please use AuthMeBungee instead! Aborting!");
|
||||||
stopOrUnload();
|
stopOrUnload();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -178,11 +183,11 @@ public class AuthMe extends JavaPlugin {
|
|||||||
} catch (Throwable th) {
|
} catch (Throwable th) {
|
||||||
YamlParseException yamlParseException = ExceptionUtils.findThrowableInCause(YamlParseException.class, th);
|
YamlParseException yamlParseException = ExceptionUtils.findThrowableInCause(YamlParseException.class, th);
|
||||||
if (yamlParseException == null) {
|
if (yamlParseException == null) {
|
||||||
logger.logException("已中止AuthMeReReloaded的初始化,原因:", th);
|
logger.logException("Aborting initialization of AuthMe:", th);
|
||||||
th.printStackTrace();
|
th.printStackTrace();
|
||||||
} else {
|
} else {
|
||||||
logger.logException("文件 '" + yamlParseException.getFile() + "' 包含YAML语法错误. "
|
logger.logException("File '" + yamlParseException.getFile() + "' contains invalid YAML. "
|
||||||
+ "请尝试在 https://yamllint.com 中运行文件内容", yamlParseException);
|
+ "Please run its contents through http://yamllint.com", yamlParseException);
|
||||||
}
|
}
|
||||||
stopOrUnload();
|
stopOrUnload();
|
||||||
return;
|
return;
|
||||||
@@ -196,42 +201,34 @@ public class AuthMe extends JavaPlugin {
|
|||||||
cleanupTask.runTaskTimerAsynchronously(this, CLEANUP_INTERVAL, CLEANUP_INTERVAL);
|
cleanupTask.runTaskTimerAsynchronously(this, CLEANUP_INTERVAL, CLEANUP_INTERVAL);
|
||||||
// Do a backup on start
|
// Do a backup on start
|
||||||
backupService.doBackup(BackupService.BackupCause.START);
|
backupService.doBackup(BackupService.BackupCause.START);
|
||||||
|
|
||||||
// Set up Metrics
|
// Set up Metrics
|
||||||
OnStartupTasks.sendMetrics(this, settings);
|
OnStartupTasks.sendMetrics(this, settings);
|
||||||
|
if (settings.getProperty(SecuritySettings.SHOW_STARTUP_BANNER)) {
|
||||||
// Successful message
|
logger.info("\n" + " ___ __ __ __ ___ \n" +
|
||||||
logger.info("AuthMeReReloaded 已成功启动!");
|
" / | __ __/ /_/ /_ / |/ /__ \n" +
|
||||||
|
" / /| |/ / / / __/ __ \\/ /|_/ / _ \\\n" +
|
||||||
|
" / ___ / /_/ / /_/ / / / / / / __/\n" +
|
||||||
|
"/_/ |_\\__,_/\\__/_/ /_/_/ /_/\\___/ \n" +
|
||||||
|
" ");
|
||||||
|
}
|
||||||
|
//detect server brand with classloader
|
||||||
|
checkServerType();
|
||||||
|
try {
|
||||||
|
Objects.requireNonNull(getCommand("register")).setTabCompleter(new TabCompleteHandler());
|
||||||
|
Objects.requireNonNull(getCommand("login")).setTabCompleter(new TabCompleteHandler());
|
||||||
|
} catch (NullPointerException ignored) {
|
||||||
|
}
|
||||||
|
logger.info("AuthMeReReloaded is enabled successfully!");
|
||||||
// Purge on start if enabled
|
// Purge on start if enabled
|
||||||
PurgeService purgeService = injector.getSingleton(PurgeService.class);
|
PurgeService purgeService = injector.getSingleton(PurgeService.class);
|
||||||
purgeService.runAutoPurge();
|
purgeService.runAutoPurge();
|
||||||
// 注册玩家退出事件监听
|
logger.info("GitHub: https://github.com/HaHaWTH/AuthMeReReloaded/");
|
||||||
if (settings.getProperty(SecuritySettings.ANTI_GHOST_PLAYERS) || settings.getProperty(SecuritySettings.SMART_ASYNC_TELEPORT)/* || settings.getProperty(SecuritySettings.GUI_CAPTCHA)*/) {
|
|
||||||
if (settings.getProperty(SecuritySettings.ANTI_GHOST_PLAYERS)) {
|
|
||||||
getServer().getPluginManager().registerEvents(new PlayerQuitListener((Plugin) this), this);
|
|
||||||
}
|
|
||||||
if (settings.getProperty(SecuritySettings.SMART_ASYNC_TELEPORT)) {
|
|
||||||
logger.info("(RC2)SmartAsyncTeleport功能已注册");
|
|
||||||
AuthMe.SATEnabled = true;
|
|
||||||
}
|
|
||||||
if (settings.getProperty(SecuritySettings.GUI_CAPTCHA) && getServer().getPluginManager().isPluginEnabled("ProtocolLib")) {
|
|
||||||
getServer().getPluginManager().registerEvents(new RegisterListener((Plugin) this), this);
|
|
||||||
logger.info("(RC2)GUI验证码功能已注册");
|
|
||||||
AuthMe.GUIEnabled = true;
|
|
||||||
} else if (settings.getProperty(SecuritySettings.GUI_CAPTCHA) && !getServer().getPluginManager().isPluginEnabled("ProtocolLib")) {
|
|
||||||
logger.warning("ProtocolLib未加载,GUI验证码功能无法使用");
|
|
||||||
}
|
|
||||||
logger.info("以上功能尚在测试中,如有问题请反馈,如需关闭请前往config.yml修改");
|
|
||||||
logger.info("反馈地址: github.com/HaHaWTH/AuthMeReReloaded/issues");
|
|
||||||
}
|
|
||||||
if (settings.getProperty(SecuritySettings.CHECK_FOR_UPDATES)) {
|
if (settings.getProperty(SecuritySettings.CHECK_FOR_UPDATES)) {
|
||||||
checkForUpdates();
|
checkForUpdates();
|
||||||
}
|
}
|
||||||
if (SHAEnabled){
|
|
||||||
//shaChecker();
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
public File pluginfile = getFile();
|
|
||||||
/**
|
/**
|
||||||
* Load the version and build number of the plugin from the description file.
|
* Load the version and build number of the plugin from the description file.
|
||||||
*
|
*
|
||||||
@@ -263,7 +260,6 @@ public class AuthMe extends JavaPlugin {
|
|||||||
injector.register(AuthMe.class, this);
|
injector.register(AuthMe.class, this);
|
||||||
injector.register(Server.class, getServer());
|
injector.register(Server.class, getServer());
|
||||||
injector.register(PluginManager.class, getServer().getPluginManager());
|
injector.register(PluginManager.class, getServer().getPluginManager());
|
||||||
injector.register(BukkitScheduler.class, getServer().getScheduler());
|
|
||||||
injector.provide(DataFolder.class, getDataFolder());
|
injector.provide(DataFolder.class, getDataFolder());
|
||||||
injector.registerProvider(Settings.class, SettingsProvider.class);
|
injector.registerProvider(Settings.class, SettingsProvider.class);
|
||||||
injector.registerProvider(DataSource.class, DataSourceProvider.class);
|
injector.registerProvider(DataSource.class, DataSourceProvider.class);
|
||||||
@@ -306,6 +302,7 @@ public class AuthMe extends JavaPlugin {
|
|||||||
|
|
||||||
// Trigger instantiation (class not used elsewhere)
|
// Trigger instantiation (class not used elsewhere)
|
||||||
injector.getSingleton(BungeeReceiver.class);
|
injector.getSingleton(BungeeReceiver.class);
|
||||||
|
injector.getSingleton(VelocityReceiver.class);
|
||||||
|
|
||||||
// Trigger construction of API classes; they will keep track of the singleton
|
// Trigger construction of API classes; they will keep track of the singleton
|
||||||
injector.getSingleton(AuthMeApi.class);
|
injector.getSingleton(AuthMeApi.class);
|
||||||
@@ -326,10 +323,17 @@ public class AuthMe extends JavaPlugin {
|
|||||||
pluginManager.registerEvents(injector.getSingleton(EntityListener.class), this);
|
pluginManager.registerEvents(injector.getSingleton(EntityListener.class), this);
|
||||||
pluginManager.registerEvents(injector.getSingleton(ServerListener.class), this);
|
pluginManager.registerEvents(injector.getSingleton(ServerListener.class), this);
|
||||||
|
|
||||||
// Try to register 1.9 player listeners
|
|
||||||
if (isClassLoaded("org.bukkit.event.player.PlayerSwapHandItemsEvent")) {
|
// Try to register 1.8+ player listeners
|
||||||
|
if (isClassLoaded("org.bukkit.event.entity.EntityPickupItemEvent") && isClassLoaded("org.bukkit.event.player.PlayerSwapHandItemsEvent")) {
|
||||||
|
pluginManager.registerEvents(injector.getSingleton(PlayerListenerHigherThan18.class), this);
|
||||||
|
} else if (isClassLoaded("org.bukkit.event.player.PlayerSwapHandItemsEvent")) {
|
||||||
pluginManager.registerEvents(injector.getSingleton(PlayerListener19.class), this);
|
pluginManager.registerEvents(injector.getSingleton(PlayerListener19.class), this);
|
||||||
}
|
}
|
||||||
|
// Try to register 1.9 player listeners(Moved to else-if)
|
||||||
|
// if (isClassLoaded("org.bukkit.event.player.PlayerSwapHandItemsEvent")) {
|
||||||
|
// pluginManager.registerEvents(injector.getSingleton(PlayerListener19.class), this);
|
||||||
|
// }
|
||||||
|
|
||||||
// Try to register 1.9 spigot player listeners
|
// Try to register 1.9 spigot player listeners
|
||||||
if (isClassLoaded("org.spigotmc.event.player.PlayerSpawnLocationEvent")) {
|
if (isClassLoaded("org.spigotmc.event.player.PlayerSpawnLocationEvent")) {
|
||||||
@@ -340,6 +344,27 @@ public class AuthMe extends JavaPlugin {
|
|||||||
if (isClassLoaded("org.bukkit.event.entity.EntityAirChangeEvent")) {
|
if (isClassLoaded("org.bukkit.event.entity.EntityAirChangeEvent")) {
|
||||||
pluginManager.registerEvents(injector.getSingleton(PlayerListener111.class), this);
|
pluginManager.registerEvents(injector.getSingleton(PlayerListener111.class), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Register 3rd party listeners
|
||||||
|
if (settings.getProperty(SecuritySettings.FORCE_LOGIN_BEDROCK) && settings.getProperty(HooksSettings.HOOK_FLOODGATE_PLAYER) && getServer().getPluginManager().getPlugin("floodgate") != null) {
|
||||||
|
pluginManager.registerEvents(injector.getSingleton(BedrockAutoLoginListener.class), this);
|
||||||
|
} else if (settings.getProperty(SecuritySettings.FORCE_LOGIN_BEDROCK) && (!settings.getProperty(HooksSettings.HOOK_FLOODGATE_PLAYER) || getServer().getPluginManager().getPlugin("floodgate") == null)) {
|
||||||
|
logger.warning("Failed to enable BedrockAutoLogin, ensure hookFloodgate: true and floodgate is loaded.");
|
||||||
|
}
|
||||||
|
if (settings.getProperty(SecuritySettings.LOGIN_LOC_FIX_SUB_UNDERGROUND) || settings.getProperty(SecuritySettings.LOGIN_LOC_FIX_SUB_PORTAL)) {
|
||||||
|
pluginManager.registerEvents(injector.getSingleton(LoginLocationFixListener.class), this);
|
||||||
|
}
|
||||||
|
if (settings.getProperty(SecuritySettings.ANTI_GHOST_PLAYERS)) {
|
||||||
|
pluginManager.registerEvents(injector.getSingleton(DoubleLoginFixListener.class), this);
|
||||||
|
}
|
||||||
|
if (settings.getProperty(SecuritySettings.ADVANCED_SHULKER_FIX) && !isClassLoaded("org.bukkit.event.player.PlayerCommandSendEvent")) {
|
||||||
|
pluginManager.registerEvents(injector.getSingleton(AdvancedShulkerFixListener.class), this);
|
||||||
|
} else if (settings.getProperty(SecuritySettings.ADVANCED_SHULKER_FIX) && isClassLoaded("org.bukkit.event.player.PlayerCommandSendEvent")) {
|
||||||
|
logger.warning("You are running an 1.13+ minecraft server, AdvancedShulkerFix won't enable.");
|
||||||
|
}
|
||||||
|
if (settings.getProperty(SecuritySettings.PURGE_DATA_ON_QUIT)) {
|
||||||
|
pluginManager.registerEvents(injector.getSingleton(PurgeListener.class), this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -364,8 +389,8 @@ public class AuthMe extends JavaPlugin {
|
|||||||
if (onShutdownPlayerSaver != null) {
|
if (onShutdownPlayerSaver != null) {
|
||||||
onShutdownPlayerSaver.saveAllPlayers();
|
onShutdownPlayerSaver.saveAllPlayers();
|
||||||
}
|
}
|
||||||
if (settings.getProperty(EmailSettings.SHUTDOWN_MAIL)){
|
if (settings != null && settings.getProperty(EmailSettings.SHUTDOWN_MAIL)) {
|
||||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy'年'MM'月'dd'日' HH:mm:ss");
|
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy'.'MM'.'dd'.' HH:mm:ss");
|
||||||
Date date = new Date(System.currentTimeMillis());
|
Date date = new Date(System.currentTimeMillis());
|
||||||
emailService.sendShutDown(settings.getProperty(EmailSettings.SHUTDOWN_MAIL_ADDRESS),dateFormat.format(date));
|
emailService.sendShutDown(settings.getProperty(EmailSettings.SHUTDOWN_MAIL_ADDRESS),dateFormat.format(date));
|
||||||
}
|
}
|
||||||
@@ -376,109 +401,44 @@ public class AuthMe extends JavaPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Wait for tasks and close data source
|
// Wait for tasks and close data source
|
||||||
new TaskCloser(this, database).run();
|
new TaskCloser(database).run();
|
||||||
|
|
||||||
// Disabled correctly
|
// Disabled correctly
|
||||||
Consumer<String> infoLogMethod = logger == null ? getLogger()::info : logger::info;
|
Consumer<String> infoLogMethod = logger == null ? getLogger()::info : logger::info;
|
||||||
infoLogMethod.accept("AuthMe " + this.getDescription().getVersion() + " 已卸载!");
|
infoLogMethod.accept("AuthMe " + this.getDescription().getVersion() + " is unloaded successfully!");
|
||||||
ConsoleLogger.closeFileWriter();
|
ConsoleLogger.closeFileWriter();
|
||||||
}
|
}
|
||||||
private static final String owner = "HaHaWTH";
|
|
||||||
private static final String owner_gitee = "Shixuehan114514";
|
|
||||||
private static final String repo = "AuthMeReReloaded";
|
|
||||||
private void checkForUpdates() {
|
private void checkForUpdates() {
|
||||||
logger.info("正在检查更新...");
|
logger.info("Checking for updates...");
|
||||||
Bukkit.getScheduler().runTaskAsynchronously(this, () -> {
|
Updater updater = new Updater(pluginBuild + pluginBuildNumber);
|
||||||
try {
|
bukkitService.runTaskAsynchronously(() -> {
|
||||||
// Get the latest version number from GitHub
|
if (updater.isUpdateAvailable()) {
|
||||||
|
String message = "New version available! Latest:" + updater.getLatestVersion() + " Current:" + pluginBuild + pluginBuildNumber;
|
||||||
URL url = new URL("https://api.github.com/repos/" + owner + "/" + repo + "/releases/latest");
|
logger.warning(message);
|
||||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
logger.warning("Download from here: https://modrinth.com/plugin/authmerereloaded");
|
||||||
conn.setConnectTimeout(10000); // 设置连接超时为10秒
|
} else {
|
||||||
conn.setReadTimeout(10000); // 设置读取超时为10秒
|
logger.info("You are running the latest version.");
|
||||||
Scanner scanner = new Scanner(conn.getInputStream());
|
|
||||||
String response = scanner.useDelimiter("\\Z").next();
|
|
||||||
scanner.close();
|
|
||||||
|
|
||||||
// Parse JSON response and extract version number
|
|
||||||
String latestVersion = response.substring(response.indexOf("tag_name") + 11);
|
|
||||||
latestVersion = latestVersion.substring(0, latestVersion.indexOf("\""));
|
|
||||||
if ((pluginBuild + pluginBuildNumber).equals(latestVersion)) {
|
|
||||||
getLogger().log(Level.INFO,"当前为最新版本");
|
|
||||||
}
|
|
||||||
if (!(pluginBuild + pluginBuildNumber).equals(latestVersion)) {
|
|
||||||
// Display update message to users
|
|
||||||
String message = "有新版本可用! 最新版本:" + latestVersion + " 当前版本:" + pluginBuild + pluginBuildNumber;
|
|
||||||
getLogger().log(Level.INFO, message);
|
|
||||||
getLogger().log(Level.INFO,"下载地址:github.com/HaHaWTH/AuthMeReReloaded/releases/latest");
|
|
||||||
}
|
|
||||||
}catch (IOException e) {
|
|
||||||
getLogger().log(Level.WARNING,"从GitHub检查更新时出现错误,原因: " + e.getMessage());
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
private static final String SHA_URL = "https://raw.githubusercontent.com/"+ owner +"/"+ repo + "/master/"+pluginBuild +pluginBuildNumber+ ".sha";
|
|
||||||
private static final String ALGORITHM = "SHA-256";
|
|
||||||
private static final String PROXY_URL = "https://ghproxy.com/";
|
|
||||||
private static final String SHA_URL_GITEE = "https://gitee.com/"+ owner_gitee +"/"+ repo + "/raw/master/"+pluginBuild+pluginBuildNumber+ ".sha";
|
|
||||||
|
|
||||||
// public void shaChecker() {
|
|
||||||
// // 请求SHA文件
|
private void checkServerType() {
|
||||||
//
|
if (isClassLoaded("io.papermc.paper.threadedregions.RegionizedServer")) {
|
||||||
// String actualSha;
|
logger.info("AuthMeReReloaded is running on Folia");
|
||||||
// try {
|
} else if (isClassLoaded("com.destroystokyo.paper.PaperConfig")) {
|
||||||
// URL url;
|
logger.info("AuthMeReReloaded is running on Paper");
|
||||||
// if(settings.getProperty(SecuritySettings.SHA_CHECK_METHOD).equals("github")) {
|
} else if (isClassLoaded("catserver.server.CatServerConfig")) {
|
||||||
// url = new URL(SHA_URL);
|
logger.info("AuthMeReReloaded is running on CatServer");
|
||||||
// logger.info("正在检查文件完整性...(GitHub)");
|
} else if (isClassLoaded("org.spigotmc.SpigotConfig")) {
|
||||||
// } else if(settings.getProperty(SecuritySettings.SHA_CHECK_METHOD).equals("ghproxy")) {
|
logger.info("AuthMeReReloaded is running on Spigot");
|
||||||
// url = new URL(PROXY_URL + SHA_URL);
|
} else if (isClassLoaded("org.bukkit.craftbukkit.CraftServer")) {
|
||||||
// logger.info("正在检查文件完整性...(GhProxy)");
|
logger.info("AuthMeReReloaded is running on Bukkit");
|
||||||
// } else if (settings.getProperty(SecuritySettings.SHA_CHECK_METHOD).equals("gitee")) {
|
} else {
|
||||||
// url = new URL(SHA_URL_GITEE);
|
logger.info("AuthMeReReloaded is running on Unknown*");
|
||||||
// logger.info("正在检查文件完整性...(Gitee)");
|
}
|
||||||
// }else {
|
}
|
||||||
// logger.warning("未知的SHA检查方法,将从GitHub获取SHA文件");
|
|
||||||
// url = new URL(SHA_URL);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
|
||||||
// conn.setConnectTimeout(10000);
|
|
||||||
// conn.setReadTimeout(9000);
|
|
||||||
// conn.setRequestMethod("GET");
|
|
||||||
// InputStream stream = conn.getInputStream();
|
|
||||||
// ByteArrayOutputStream result = new ByteArrayOutputStream();
|
|
||||||
// byte[] buffer = new byte[1024];
|
|
||||||
// int length;
|
|
||||||
// while ((length = stream.read(buffer)) != -1) {
|
|
||||||
// result.write(buffer, 0, length);
|
|
||||||
// }
|
|
||||||
// String expectedSha = result.toString().trim();
|
|
||||||
// // 计算插件文件的SHA值
|
|
||||||
// MessageDigest md = MessageDigest.getInstance(ALGORITHM);
|
|
||||||
// byte[] fileBytes = Files.readAllBytes(pluginfile.toPath());
|
|
||||||
// byte[] hashBytes = md.digest(fileBytes);
|
|
||||||
// StringBuilder sb = new StringBuilder();
|
|
||||||
// for (byte b : hashBytes) {
|
|
||||||
// sb.append(String.format("%02x", b));
|
|
||||||
// }
|
|
||||||
// actualSha = sb.toString();
|
|
||||||
//
|
|
||||||
// // 比较SHA值并加载插件
|
|
||||||
// if (expectedSha.equals(actualSha)) {
|
|
||||||
// logger.info("SHA联网安全校验完毕");
|
|
||||||
// } else {
|
|
||||||
// // SHA值不匹配,插件可能被篡改
|
|
||||||
// logger.warning("SHA值不匹配,插件被篡改");
|
|
||||||
// stopOrUnload();
|
|
||||||
// }
|
|
||||||
// }catch (NoSuchAlgorithmException | IOException e){
|
|
||||||
// logger.warning("SHA校验失败,请尝试切换校验API");
|
|
||||||
// logger.warning("您当前请求的API为:" + settings.getProperty(SecuritySettings.SHA_CHECK_METHOD));
|
|
||||||
// stopOrUnload();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ public final class ConsoleLogger {
|
|||||||
*/
|
*/
|
||||||
public void warning(String message) {
|
public void warning(String message) {
|
||||||
logger.warning(message);
|
logger.warning(message);
|
||||||
writeLog("[警告] " + message);
|
writeLog("[WARN] " + message);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -128,7 +128,7 @@ public final class ConsoleLogger {
|
|||||||
*/
|
*/
|
||||||
public void info(String message) {
|
public void info(String message) {
|
||||||
logger.info(message);
|
logger.info(message);
|
||||||
writeLog("[信息] " + message);
|
writeLog("[INFO] " + message);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -142,7 +142,7 @@ public final class ConsoleLogger {
|
|||||||
public void fine(String message) {
|
public void fine(String message) {
|
||||||
if (logLevel.includes(LogLevel.FINE)) {
|
if (logLevel.includes(LogLevel.FINE)) {
|
||||||
logger.info(message);
|
logger.info(message);
|
||||||
writeLog("[信息:调试] " + message);
|
writeLog("[INFO:FINE] " + message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,7 +215,7 @@ public final class ConsoleLogger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void logAndWriteWithDebugPrefix(String message) {
|
private void logAndWriteWithDebugPrefix(String message) {
|
||||||
String debugMessage = "[信息:调试] " + message;
|
String debugMessage = "[INFO:DEBUG] " + message;
|
||||||
logger.info(debugMessage);
|
logger.info(debugMessage);
|
||||||
writeLog(debugMessage);
|
writeLog(debugMessage);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import java.util.Optional;
|
|||||||
* AuthMeApi authmeApi = AuthMeApi.getInstance();
|
* AuthMeApi authmeApi = AuthMeApi.getInstance();
|
||||||
* </code>
|
* </code>
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
public class AuthMeApi {
|
public class AuthMeApi {
|
||||||
|
|
||||||
private static AuthMeApi singleton;
|
private static AuthMeApi singleton;
|
||||||
@@ -265,6 +266,16 @@ public class AuthMeApi {
|
|||||||
management.forceLogin(player);
|
management.forceLogin(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Force a player to login, i.e. the player is logged in without needing his password.
|
||||||
|
*
|
||||||
|
* @param player The player to log in
|
||||||
|
* @param quiet Whether to suppress the login message
|
||||||
|
*/
|
||||||
|
public void forceLogin(Player player, boolean quiet) {
|
||||||
|
management.forceLogin(player, quiet);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Force a player to logout.
|
* Force a player to logout.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -84,14 +84,14 @@ public final class CommandUtils {
|
|||||||
* @return formatted command syntax incl. arguments
|
* @return formatted command syntax incl. arguments
|
||||||
*/
|
*/
|
||||||
public static String buildSyntax(CommandDescription command, List<String> correctLabels) {
|
public static String buildSyntax(CommandDescription command, List<String> correctLabels) {
|
||||||
String commandSyntax = ChatColor.WHITE + "/" + correctLabels.get(0) + ChatColor.YELLOW;
|
StringBuilder commandSyntax = new StringBuilder(ChatColor.WHITE + "/" + correctLabels.get(0) + ChatColor.YELLOW);
|
||||||
for (int i = 1; i < correctLabels.size(); ++i) {
|
for (int i = 1; i < correctLabels.size(); ++i) {
|
||||||
commandSyntax += " " + correctLabels.get(i);
|
commandSyntax.append(" ").append(correctLabels.get(i));
|
||||||
}
|
}
|
||||||
for (CommandArgumentDescription argument : command.getArguments()) {
|
for (CommandArgumentDescription argument : command.getArguments()) {
|
||||||
commandSyntax += " " + formatArgument(argument);
|
commandSyntax.append(" ").append(formatArgument(argument));
|
||||||
}
|
}
|
||||||
return commandSyntax;
|
return commandSyntax.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -17,9 +17,9 @@ public abstract class PlayerCommand implements ExecutableCommand {
|
|||||||
} else {
|
} else {
|
||||||
String alternative = getAlternativeCommand();
|
String alternative = getAlternativeCommand();
|
||||||
if (alternative != null) {
|
if (alternative != null) {
|
||||||
sender.sendMessage("此命令仅限玩家使用!请使用 " + alternative + " .");
|
sender.sendMessage("Player only! Please use " + alternative + " instead.");
|
||||||
} else {
|
} else {
|
||||||
sender.sendMessage("此命令只能被玩家执行.");
|
sender.sendMessage("This command is only for players.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package fr.xephi.authme.command;
|
||||||
|
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.command.TabCompleter;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class TabCompleteHandler implements TabCompleter {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, String[] args) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,12 +7,12 @@ import fr.xephi.authme.ConsoleLogger;
|
|||||||
import fr.xephi.authme.command.ExecutableCommand;
|
import fr.xephi.authme.command.ExecutableCommand;
|
||||||
import fr.xephi.authme.datasource.converter.Converter;
|
import fr.xephi.authme.datasource.converter.Converter;
|
||||||
import fr.xephi.authme.datasource.converter.CrazyLoginConverter;
|
import fr.xephi.authme.datasource.converter.CrazyLoginConverter;
|
||||||
|
import fr.xephi.authme.datasource.converter.H2ToSqlite;
|
||||||
import fr.xephi.authme.datasource.converter.LoginSecurityConverter;
|
import fr.xephi.authme.datasource.converter.LoginSecurityConverter;
|
||||||
import fr.xephi.authme.datasource.converter.MySqlToSqlite;
|
import fr.xephi.authme.datasource.converter.MySqlToSqlite;
|
||||||
import fr.xephi.authme.datasource.converter.RakamakConverter;
|
|
||||||
import fr.xephi.authme.datasource.converter.RoyalAuthConverter;
|
import fr.xephi.authme.datasource.converter.RoyalAuthConverter;
|
||||||
|
import fr.xephi.authme.datasource.converter.SqliteToH2;
|
||||||
import fr.xephi.authme.datasource.converter.SqliteToSql;
|
import fr.xephi.authme.datasource.converter.SqliteToSql;
|
||||||
import fr.xephi.authme.datasource.converter.VAuthConverter;
|
|
||||||
import fr.xephi.authme.datasource.converter.XAuthConverter;
|
import fr.xephi.authme.datasource.converter.XAuthConverter;
|
||||||
import fr.xephi.authme.message.MessageKey;
|
import fr.xephi.authme.message.MessageKey;
|
||||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||||
@@ -84,11 +84,11 @@ public class ConverterCommand implements ExecutableCommand {
|
|||||||
return ImmutableSortedMap.<String, Class<? extends Converter>>naturalOrder()
|
return ImmutableSortedMap.<String, Class<? extends Converter>>naturalOrder()
|
||||||
.put("xauth", XAuthConverter.class)
|
.put("xauth", XAuthConverter.class)
|
||||||
.put("crazylogin", CrazyLoginConverter.class)
|
.put("crazylogin", CrazyLoginConverter.class)
|
||||||
.put("rakamak", RakamakConverter.class)
|
|
||||||
.put("royalauth", RoyalAuthConverter.class)
|
.put("royalauth", RoyalAuthConverter.class)
|
||||||
.put("vauth", VAuthConverter.class)
|
|
||||||
.put("sqlitetosql", SqliteToSql.class)
|
.put("sqlitetosql", SqliteToSql.class)
|
||||||
.put("mysqltosqlite", MySqlToSqlite.class)
|
.put("mysqltosqlite", MySqlToSqlite.class)
|
||||||
|
.put("sqlitetoh2", SqliteToH2.class)
|
||||||
|
.put("h2tosqlite", H2ToSqlite.class)
|
||||||
.put("loginsecurity", LoginSecurityConverter.class)
|
.put("loginsecurity", LoginSecurityConverter.class)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
package fr.xephi.authme.command.executable.authme;
|
package fr.xephi.authme.command.executable.authme;
|
||||||
|
|
||||||
import fr.xephi.authme.ConsoleLogger;
|
|
||||||
import fr.xephi.authme.command.PlayerCommand;
|
import fr.xephi.authme.command.PlayerCommand;
|
||||||
|
import fr.xephi.authme.service.BukkitService;
|
||||||
import fr.xephi.authme.settings.Settings;
|
import fr.xephi.authme.settings.Settings;
|
||||||
import fr.xephi.authme.settings.SpawnLoader;
|
import fr.xephi.authme.settings.SpawnLoader;
|
||||||
import fr.xephi.authme.settings.properties.SecuritySettings;
|
|
||||||
import fr.xephi.authme.util.TeleportUtils;
|
import fr.xephi.authme.util.TeleportUtils;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import fr.xephi.authme.AuthMe;
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -19,17 +18,17 @@ public class FirstSpawnCommand extends PlayerCommand {
|
|||||||
private Settings settings;
|
private Settings settings;
|
||||||
@Inject
|
@Inject
|
||||||
private SpawnLoader spawnLoader;
|
private SpawnLoader spawnLoader;
|
||||||
|
@Inject
|
||||||
|
private BukkitService bukkitService;
|
||||||
@Override
|
@Override
|
||||||
public void runCommand(Player player, List<String> arguments) {
|
public void runCommand(Player player, List<String> arguments) {
|
||||||
if (spawnLoader.getFirstSpawn() == null) {
|
if (spawnLoader.getFirstSpawn() == null) {
|
||||||
player.sendMessage("[AuthMe] First spawn has failed, please try to define the first spawn");
|
player.sendMessage("[AuthMe] First spawn has failed, please try to define the first spawn");
|
||||||
} else {
|
} else {
|
||||||
//String name= player.getName();
|
//String name= player.getName();
|
||||||
if(AuthMe.SATEnabled) {
|
bukkitService.runTaskIfFolia(player, () -> {
|
||||||
TeleportUtils.teleport(player, spawnLoader.getFirstSpawn());
|
TeleportUtils.teleport(player, spawnLoader.getFirstSpawn());
|
||||||
} else {
|
});
|
||||||
player.teleport(spawnLoader.getFirstSpawn());
|
|
||||||
}
|
|
||||||
//player.teleport(spawnLoader.getFirstSpawn());
|
//player.teleport(spawnLoader.getFirstSpawn());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,7 +78,8 @@ public class RegisterAdminCommand implements ExecutableCommand {
|
|||||||
final Player player = bukkitService.getPlayerExact(playerName);
|
final Player player = bukkitService.getPlayerExact(playerName);
|
||||||
if (player != null) {
|
if (player != null) {
|
||||||
bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(() ->
|
bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(() ->
|
||||||
player.kickPlayer(commonService.retrieveSingleMessage(player, MessageKey.KICK_FOR_ADMIN_REGISTER)));
|
// AuthMeReReloaded - Folia compatibility
|
||||||
|
bukkitService.runTaskIfFolia(player, () -> player.kickPlayer(commonService.retrieveSingleMessage(player, MessageKey.KICK_FOR_ADMIN_REGISTER))));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,9 +45,7 @@ public class SetEmailCommand implements ExecutableCommand {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bukkitService.runTaskOptionallyAsync(new Runnable() {
|
bukkitService.runTaskOptionallyAsync(() -> { // AuthMeReReloaded - Folia compatibility
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
// Validate the user
|
// Validate the user
|
||||||
PlayerAuth auth = dataSource.getAuth(playerName);
|
PlayerAuth auth = dataSource.getAuth(playerName);
|
||||||
if (auth == null) {
|
if (auth == null) {
|
||||||
@@ -72,7 +70,6 @@ public class SetEmailCommand implements ExecutableCommand {
|
|||||||
|
|
||||||
// Show a status message
|
// Show a status message
|
||||||
commonService.send(sender, MessageKey.EMAIL_CHANGED_SUCCESS);
|
commonService.send(sender, MessageKey.EMAIL_CHANGED_SUCCESS);
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
package fr.xephi.authme.command.executable.authme;
|
package fr.xephi.authme.command.executable.authme;
|
||||||
|
|
||||||
import fr.xephi.authme.command.PlayerCommand;
|
import fr.xephi.authme.command.PlayerCommand;
|
||||||
|
import fr.xephi.authme.service.BukkitService;
|
||||||
import fr.xephi.authme.settings.SpawnLoader;
|
import fr.xephi.authme.settings.SpawnLoader;
|
||||||
|
import fr.xephi.authme.util.TeleportUtils;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
@@ -11,13 +13,15 @@ public class SpawnCommand extends PlayerCommand {
|
|||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private SpawnLoader spawnLoader;
|
private SpawnLoader spawnLoader;
|
||||||
|
@Inject
|
||||||
|
private BukkitService bukkitService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void runCommand(Player player, List<String> arguments) {
|
public void runCommand(Player player, List<String> arguments) {
|
||||||
if (spawnLoader.getSpawn() == null) {
|
if (spawnLoader.getSpawn() == null) {
|
||||||
player.sendMessage("[AuthMe] Spawn has failed, please try to define the spawn");
|
player.sendMessage("[AuthMe] Spawn has failed, please try to define the spawn");
|
||||||
} else {
|
} else {
|
||||||
player.teleport(spawnLoader.getSpawn());
|
bukkitService.runTaskIfFolia(player, () -> TeleportUtils.teleport(player, spawnLoader.getSpawn()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package fr.xephi.authme.command.executable.authme;
|
|||||||
import fr.xephi.authme.AuthMe;
|
import fr.xephi.authme.AuthMe;
|
||||||
import fr.xephi.authme.command.ExecutableCommand;
|
import fr.xephi.authme.command.ExecutableCommand;
|
||||||
import fr.xephi.authme.service.BukkitService;
|
import fr.xephi.authme.service.BukkitService;
|
||||||
|
import fr.xephi.authme.settings.Settings;
|
||||||
|
import fr.xephi.authme.settings.properties.DatabaseSettings;
|
||||||
import org.bukkit.ChatColor;
|
import org.bukkit.ChatColor;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
@@ -17,6 +19,8 @@ public class VersionCommand implements ExecutableCommand {
|
|||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private BukkitService bukkitService;
|
private BukkitService bukkitService;
|
||||||
|
@Inject
|
||||||
|
private Settings settings;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void executeCommand(CommandSender sender, List<String> arguments) {
|
public void executeCommand(CommandSender sender, List<String> arguments) {
|
||||||
@@ -24,6 +28,7 @@ public class VersionCommand implements ExecutableCommand {
|
|||||||
sender.sendMessage(ChatColor.GOLD + "==========[ " + AuthMe.getPluginName() + " ABOUT ]==========");
|
sender.sendMessage(ChatColor.GOLD + "==========[ " + AuthMe.getPluginName() + " ABOUT ]==========");
|
||||||
sender.sendMessage(ChatColor.GOLD + "Version: " + ChatColor.WHITE + AuthMe.getPluginName()
|
sender.sendMessage(ChatColor.GOLD + "Version: " + ChatColor.WHITE + AuthMe.getPluginName()
|
||||||
+ " v" + AuthMe.getPluginVersion() + ChatColor.GRAY + " (build: " + AuthMe.getPluginBuildNumber() + ")");
|
+ " v" + AuthMe.getPluginVersion() + ChatColor.GRAY + " (build: " + AuthMe.getPluginBuildNumber() + ")");
|
||||||
|
sender.sendMessage(ChatColor.GOLD + "Database Implementation: " + ChatColor.WHITE + settings.getProperty(DatabaseSettings.BACKEND).toString());
|
||||||
sender.sendMessage(ChatColor.GOLD + "Authors:");
|
sender.sendMessage(ChatColor.GOLD + "Authors:");
|
||||||
Collection<Player> onlinePlayers = bukkitService.getOnlinePlayers();
|
Collection<Player> onlinePlayers = bukkitService.getOnlinePlayers();
|
||||||
printDeveloper(sender, "Gabriele C.", "sgdc3", "Project manager, Contributor", onlinePlayers);
|
printDeveloper(sender, "Gabriele C.", "sgdc3", "Project manager, Contributor", onlinePlayers);
|
||||||
|
|||||||
+4
@@ -8,6 +8,7 @@ import fr.xephi.authme.process.Management;
|
|||||||
import fr.xephi.authme.service.CommonService;
|
import fr.xephi.authme.service.CommonService;
|
||||||
import fr.xephi.authme.service.ValidationService;
|
import fr.xephi.authme.service.ValidationService;
|
||||||
import fr.xephi.authme.service.ValidationService.ValidationResult;
|
import fr.xephi.authme.service.ValidationService.ValidationResult;
|
||||||
|
import fr.xephi.authme.settings.properties.SecuritySettings;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
@@ -42,12 +43,15 @@ public class ChangePasswordCommand extends PlayerCommand {
|
|||||||
commonService.send(player, MessageKey.NOT_LOGGED_IN);
|
commonService.send(player, MessageKey.NOT_LOGGED_IN);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (commonService.getProperty(SecuritySettings.CHANGE_PASSWORD_EMAIL_VERIFICATION_REQUIRED)) {
|
||||||
// Check if the user has been verified or not
|
// Check if the user has been verified or not
|
||||||
if (codeManager.isVerificationRequired(player)) {
|
if (codeManager.isVerificationRequired(player)) {
|
||||||
codeManager.codeExistOrGenerateNew(name);
|
codeManager.codeExistOrGenerateNew(name);
|
||||||
commonService.send(player, MessageKey.VERIFICATION_CODE_REQUIRED);
|
commonService.send(player, MessageKey.VERIFICATION_CODE_REQUIRED);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String oldPassword = arguments.get(0);
|
String oldPassword = arguments.get(0);
|
||||||
String newPassword = arguments.get(1);
|
String newPassword = arguments.get(1);
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import fr.xephi.authme.process.register.executors.PasswordRegisterParams;
|
|||||||
import fr.xephi.authme.process.register.executors.RegistrationMethod;
|
import fr.xephi.authme.process.register.executors.RegistrationMethod;
|
||||||
import fr.xephi.authme.process.register.executors.TwoFactorRegisterParams;
|
import fr.xephi.authme.process.register.executors.TwoFactorRegisterParams;
|
||||||
import fr.xephi.authme.security.HashAlgorithm;
|
import fr.xephi.authme.security.HashAlgorithm;
|
||||||
|
import fr.xephi.authme.service.BukkitService;
|
||||||
import fr.xephi.authme.service.CommonService;
|
import fr.xephi.authme.service.CommonService;
|
||||||
import fr.xephi.authme.service.ValidationService;
|
import fr.xephi.authme.service.ValidationService;
|
||||||
import fr.xephi.authme.settings.properties.EmailSettings;
|
import fr.xephi.authme.settings.properties.EmailSettings;
|
||||||
@@ -24,8 +25,6 @@ import org.bukkit.entity.Player;
|
|||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Timer;
|
|
||||||
import java.util.TimerTask;
|
|
||||||
|
|
||||||
import static fr.xephi.authme.process.register.RegisterSecondaryArgument.CONFIRMATION;
|
import static fr.xephi.authme.process.register.RegisterSecondaryArgument.CONFIRMATION;
|
||||||
import static fr.xephi.authme.process.register.RegisterSecondaryArgument.EMAIL_MANDATORY;
|
import static fr.xephi.authme.process.register.RegisterSecondaryArgument.EMAIL_MANDATORY;
|
||||||
@@ -46,6 +45,9 @@ public class RegisterCommand extends PlayerCommand {
|
|||||||
@Inject
|
@Inject
|
||||||
private CommonService commonService;
|
private CommonService commonService;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private BukkitService bukkitService;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private DataSource dataSource;
|
private DataSource dataSource;
|
||||||
|
|
||||||
@@ -175,20 +177,15 @@ public class RegisterCommand extends PlayerCommand {
|
|||||||
} else if (isSecondArgValidForEmailRegistration(player, arguments)) {
|
} else if (isSecondArgValidForEmailRegistration(player, arguments)) {
|
||||||
management.performRegister(RegistrationMethod.EMAIL_REGISTRATION,
|
management.performRegister(RegistrationMethod.EMAIL_REGISTRATION,
|
||||||
EmailRegisterParams.of(player, email));
|
EmailRegisterParams.of(player, email));
|
||||||
Timer timer = new Timer();
|
if (commonService.getProperty(RegistrationSettings.UNREGISTER_ON_EMAIL_VERIFICATION_FAILURE) && commonService.getProperty(RegistrationSettings.UNREGISTER_AFTER_MINUTES) > 0) {
|
||||||
timer.schedule(new TimerTask() {
|
bukkitService.runTaskLater(player, () -> {
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (dataSource.getAuth(player.getName()) != null) {
|
if (dataSource.getAuth(player.getName()) != null) {
|
||||||
if (dataSource.getAuth(player.getName()).getLastLogin() == null) {
|
if (dataSource.getAuth(player.getName()).getLastLogin() == null) {
|
||||||
management.performUnregisterByAdmin(null, player.getName(), player);
|
management.performUnregisterByAdmin(null, player.getName(), player);
|
||||||
timer.cancel();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
timer.cancel();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, 600000);
|
}, 60 * 20 * commonService.getProperty(RegistrationSettings.UNREGISTER_AFTER_MINUTES));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ public class TempbanManager implements SettingsDependent, HasCleanup {
|
|||||||
long newTime = expires.getTime() + (length * MILLIS_PER_MINUTE);
|
long newTime = expires.getTime() + (length * MILLIS_PER_MINUTE);
|
||||||
expires.setTime(newTime);
|
expires.setTime(newTime);
|
||||||
|
|
||||||
bukkitService.scheduleSyncDelayedTask(() -> {
|
bukkitService.runTask(player,() -> { // AuthMeReReloaded - Folia compatibility
|
||||||
if (customCommand.isEmpty()) {
|
if (customCommand.isEmpty()) {
|
||||||
bukkitService.banIp(ip, reason, expires, "AuthMe");
|
bukkitService.banIp(ip, reason, expires, "AuthMe");
|
||||||
player.kickPlayer(reason);
|
player.kickPlayer(reason);
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ import java.util.Locale;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import static fr.xephi.authme.AuthMe.getScheduler;
|
||||||
|
|
||||||
public class VerificationCodeManager implements SettingsDependent, HasCleanup {
|
public class VerificationCodeManager implements SettingsDependent, HasCleanup {
|
||||||
|
|
||||||
private final EmailService emailService;
|
private final EmailService emailService;
|
||||||
@@ -133,8 +135,9 @@ public class VerificationCodeManager implements SettingsDependent, HasCleanup {
|
|||||||
* @param name the name of the player to generate a code for
|
* @param name the name of the player to generate a code for
|
||||||
*/
|
*/
|
||||||
private void generateCode(String name) {
|
private void generateCode(String name) {
|
||||||
|
getScheduler().runTaskAsynchronously(() -> {
|
||||||
DataSourceValue<String> emailResult = dataSource.getEmail(name);
|
DataSourceValue<String> emailResult = dataSource.getEmail(name);
|
||||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy'年'MM'月'dd'日' HH:mm:ss");
|
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy'-'MM'-'dd'-' HH:mm:ss");
|
||||||
Date date = new Date(System.currentTimeMillis());
|
Date date = new Date(System.currentTimeMillis());
|
||||||
if (emailResult.rowExists()) {
|
if (emailResult.rowExists()) {
|
||||||
final String email = emailResult.getValue();
|
final String email = emailResult.getValue();
|
||||||
@@ -144,6 +147,7 @@ public class VerificationCodeManager implements SettingsDependent, HasCleanup {
|
|||||||
emailService.sendVerificationMail(name, email, code, dateFormat.format(date));
|
emailService.sendVerificationMail(name, email, code, dateFormat.format(date));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
package fr.xephi.authme.data.limbo;
|
package fr.xephi.authme.data.limbo;
|
||||||
|
|
||||||
|
import com.github.Anon8281.universalScheduler.scheduling.tasks.MyScheduledTask;
|
||||||
import fr.xephi.authme.task.MessageTask;
|
import fr.xephi.authme.task.MessageTask;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.scheduler.BukkitTask;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@@ -22,8 +22,9 @@ public class LimboPlayer {
|
|||||||
private final Location loc;
|
private final Location loc;
|
||||||
private final float walkSpeed;
|
private final float walkSpeed;
|
||||||
private final float flySpeed;
|
private final float flySpeed;
|
||||||
private BukkitTask timeoutTask = null;
|
private MyScheduledTask timeoutTask = null;
|
||||||
private MessageTask messageTask = null;
|
private MessageTask messageTask = null;
|
||||||
|
|
||||||
private LimboPlayerState state = LimboPlayerState.PASSWORD_REQUIRED;
|
private LimboPlayerState state = LimboPlayerState.PASSWORD_REQUIRED;
|
||||||
|
|
||||||
public LimboPlayer(Location loc, boolean operator, Collection<UserGroup> groups, boolean fly, float walkSpeed,
|
public LimboPlayer(Location loc, boolean operator, Collection<UserGroup> groups, boolean fly, float walkSpeed,
|
||||||
@@ -81,7 +82,7 @@ public class LimboPlayer {
|
|||||||
*
|
*
|
||||||
* @return The timeout task associated to the player
|
* @return The timeout task associated to the player
|
||||||
*/
|
*/
|
||||||
public BukkitTask getTimeoutTask() {
|
public MyScheduledTask getTimeoutTask() {
|
||||||
return timeoutTask;
|
return timeoutTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,7 +92,7 @@ public class LimboPlayer {
|
|||||||
*
|
*
|
||||||
* @param timeoutTask The task to set
|
* @param timeoutTask The task to set
|
||||||
*/
|
*/
|
||||||
public void setTimeoutTask(BukkitTask timeoutTask) {
|
public void setTimeoutTask(MyScheduledTask timeoutTask) {
|
||||||
if (this.timeoutTask != null) {
|
if (this.timeoutTask != null) {
|
||||||
this.timeoutTask.cancel();
|
this.timeoutTask.cancel();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package fr.xephi.authme.data.limbo;
|
package fr.xephi.authme.data.limbo;
|
||||||
|
|
||||||
|
import com.github.Anon8281.universalScheduler.scheduling.tasks.MyScheduledTask;
|
||||||
import fr.xephi.authme.data.auth.PlayerCache;
|
import fr.xephi.authme.data.auth.PlayerCache;
|
||||||
import fr.xephi.authme.data.captcha.RegistrationCaptchaManager;
|
import fr.xephi.authme.data.captcha.RegistrationCaptchaManager;
|
||||||
import fr.xephi.authme.message.MessageKey;
|
import fr.xephi.authme.message.MessageKey;
|
||||||
@@ -11,7 +12,6 @@ import fr.xephi.authme.settings.properties.RestrictionSettings;
|
|||||||
import fr.xephi.authme.task.MessageTask;
|
import fr.xephi.authme.task.MessageTask;
|
||||||
import fr.xephi.authme.task.TimeoutTask;
|
import fr.xephi.authme.task.TimeoutTask;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.scheduler.BukkitTask;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
@@ -53,7 +53,7 @@ class LimboPlayerTaskManager {
|
|||||||
if (interval > 0) {
|
if (interval > 0) {
|
||||||
String[] joinMessage = messages.retrieveSingle(player, result.messageKey, result.args).split("\n");
|
String[] joinMessage = messages.retrieveSingle(player, result.messageKey, result.args).split("\n");
|
||||||
MessageTask messageTask = new MessageTask(player, joinMessage);
|
MessageTask messageTask = new MessageTask(player, joinMessage);
|
||||||
bukkitService.runTaskTimer(messageTask, 2 * TICKS_PER_SECOND, interval * TICKS_PER_SECOND);
|
bukkitService.runTaskTimer(messageTask, 2 * TICKS_PER_SECOND, (long) interval * TICKS_PER_SECOND);
|
||||||
limbo.setMessageTask(messageTask);
|
limbo.setMessageTask(messageTask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -68,7 +68,7 @@ class LimboPlayerTaskManager {
|
|||||||
final int timeout = settings.getProperty(RestrictionSettings.TIMEOUT) * TICKS_PER_SECOND;
|
final int timeout = settings.getProperty(RestrictionSettings.TIMEOUT) * TICKS_PER_SECOND;
|
||||||
if (timeout > 0) {
|
if (timeout > 0) {
|
||||||
String message = messages.retrieveSingle(player, MessageKey.LOGIN_TIMEOUT_ERROR);
|
String message = messages.retrieveSingle(player, MessageKey.LOGIN_TIMEOUT_ERROR);
|
||||||
BukkitTask task = bukkitService.runTaskLater(new TimeoutTask(player, message, playerCache), timeout);
|
MyScheduledTask task = bukkitService.runTaskLater(new TimeoutTask(player, message, playerCache), timeout);
|
||||||
limbo.setTimeoutTask(task);
|
limbo.setTimeoutTask(task);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,18 +9,22 @@ import com.google.common.util.concurrent.ListenableFuture;
|
|||||||
import com.google.common.util.concurrent.ListeningExecutorService;
|
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||||
import com.google.common.util.concurrent.MoreExecutors;
|
import com.google.common.util.concurrent.MoreExecutors;
|
||||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||||
|
import fr.xephi.authme.AuthMe;
|
||||||
import fr.xephi.authme.ConsoleLogger;
|
import fr.xephi.authme.ConsoleLogger;
|
||||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||||
import fr.xephi.authme.data.auth.PlayerCache;
|
import fr.xephi.authme.data.auth.PlayerCache;
|
||||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||||
import fr.xephi.authme.security.crypts.HashedPassword;
|
import fr.xephi.authme.security.crypts.HashedPassword;
|
||||||
|
import fr.xephi.authme.settings.properties.DatabaseSettings;
|
||||||
import fr.xephi.authme.util.Utils;
|
import fr.xephi.authme.util.Utils;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@@ -28,11 +32,10 @@ import java.util.stream.Collectors;
|
|||||||
public class CacheDataSource implements DataSource {
|
public class CacheDataSource implements DataSource {
|
||||||
|
|
||||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(CacheDataSource.class);
|
private final ConsoleLogger logger = ConsoleLoggerFactory.get(CacheDataSource.class);
|
||||||
|
|
||||||
private final DataSource source;
|
private final DataSource source;
|
||||||
private final PlayerCache playerCache;
|
private final PlayerCache playerCache;
|
||||||
private final LoadingCache<String, Optional<PlayerAuth>> cachedAuths;
|
private final LoadingCache<String, Optional<PlayerAuth>> cachedAuths;
|
||||||
private final ListeningExecutorService executorService;
|
private ListeningExecutorService executorService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for CacheDataSource.
|
* Constructor for CacheDataSource.
|
||||||
@@ -43,13 +46,30 @@ public class CacheDataSource implements DataSource {
|
|||||||
public CacheDataSource(DataSource source, PlayerCache playerCache) {
|
public CacheDataSource(DataSource source, PlayerCache playerCache) {
|
||||||
this.source = source;
|
this.source = source;
|
||||||
this.playerCache = playerCache;
|
this.playerCache = playerCache;
|
||||||
|
if (AuthMe.settings.getProperty(DatabaseSettings.USE_VIRTUAL_THREADS)) {
|
||||||
|
try {
|
||||||
|
Method method = Executors.class.getMethod("newVirtualThreadPerTaskExecutor");
|
||||||
|
method.setAccessible(true);
|
||||||
|
ExecutorService ex = (ExecutorService) method.invoke(null);
|
||||||
|
executorService = MoreExecutors.listeningDecorator(ex);
|
||||||
|
logger.info("Using virtual threads for cache loader");
|
||||||
|
} catch (Exception e) {
|
||||||
executorService = MoreExecutors.listeningDecorator(
|
executorService = MoreExecutors.listeningDecorator(
|
||||||
Executors.newCachedThreadPool(new ThreadFactoryBuilder()
|
Executors.newCachedThreadPool(new ThreadFactoryBuilder()
|
||||||
.setDaemon(true)
|
.setDaemon(true)
|
||||||
.setNameFormat("AuthMe-CacheLoader")
|
.setNameFormat("AuthMe-CacheLoader")
|
||||||
.build())
|
.build())
|
||||||
);
|
);
|
||||||
|
logger.info("Cannot enable virtual threads, fallback to CachedThreadPool");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
executorService = MoreExecutors.listeningDecorator(
|
||||||
|
Executors.newCachedThreadPool(new ThreadFactoryBuilder()
|
||||||
|
.setDaemon(true)
|
||||||
|
.setNameFormat("AuthMe-CacheLoader")
|
||||||
|
.build())
|
||||||
|
);
|
||||||
|
}
|
||||||
cachedAuths = CacheBuilder.newBuilder()
|
cachedAuths = CacheBuilder.newBuilder()
|
||||||
.refreshAfterWrite(5, TimeUnit.MINUTES)
|
.refreshAfterWrite(5, TimeUnit.MINUTES)
|
||||||
.expireAfterAccess(15, TimeUnit.MINUTES)
|
.expireAfterAccess(15, TimeUnit.MINUTES)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ package fr.xephi.authme.datasource;
|
|||||||
* DataSource type.
|
* DataSource type.
|
||||||
*/
|
*/
|
||||||
public enum DataSourceType {
|
public enum DataSourceType {
|
||||||
|
H2,
|
||||||
|
|
||||||
MYSQL,
|
MYSQL,
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,422 @@
|
|||||||
|
package fr.xephi.authme.datasource;
|
||||||
|
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
import fr.xephi.authme.ConsoleLogger;
|
||||||
|
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||||
|
import fr.xephi.authme.datasource.columnshandler.AuthMeColumnsHandler;
|
||||||
|
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||||
|
import fr.xephi.authme.settings.Settings;
|
||||||
|
import fr.xephi.authme.settings.properties.DatabaseSettings;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.DatabaseMetaData;
|
||||||
|
import java.sql.DriverManager;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Statement;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static fr.xephi.authme.datasource.SqlDataSourceUtils.getNullableLong;
|
||||||
|
import static fr.xephi.authme.datasource.SqlDataSourceUtils.logSqlException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* H2 data source.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings({"checkstyle:AbbreviationAsWordInName"}) // Justification: Class name cannot be changed anymore
|
||||||
|
public class H2 extends AbstractSqlDataSource {
|
||||||
|
|
||||||
|
private final ConsoleLogger logger = ConsoleLoggerFactory.get(H2.class);
|
||||||
|
private final Settings settings;
|
||||||
|
private final File dataFolder;
|
||||||
|
private final String database;
|
||||||
|
private final String tableName;
|
||||||
|
private final Columns col;
|
||||||
|
private Connection con;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for H2.
|
||||||
|
*
|
||||||
|
* @param settings The settings instance
|
||||||
|
* @param dataFolder The data folder
|
||||||
|
* @throws SQLException when initialization of a SQL datasource failed
|
||||||
|
*/
|
||||||
|
public H2(Settings settings, File dataFolder) throws SQLException {
|
||||||
|
this.settings = settings;
|
||||||
|
this.dataFolder = dataFolder;
|
||||||
|
this.database = settings.getProperty(DatabaseSettings.MYSQL_DATABASE);
|
||||||
|
this.tableName = settings.getProperty(DatabaseSettings.MYSQL_TABLE);
|
||||||
|
this.col = new Columns(settings);
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.connect();
|
||||||
|
this.setup();
|
||||||
|
} catch (Exception ex) {
|
||||||
|
logger.logException("Error during H2 initialization:", ex);
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
H2(Settings settings, File dataFolder, Connection connection) {
|
||||||
|
this.settings = settings;
|
||||||
|
this.dataFolder = dataFolder;
|
||||||
|
this.database = settings.getProperty(DatabaseSettings.MYSQL_DATABASE);
|
||||||
|
this.tableName = settings.getProperty(DatabaseSettings.MYSQL_TABLE);
|
||||||
|
this.col = new Columns(settings);
|
||||||
|
this.con = connection;
|
||||||
|
this.columnsHandler = AuthMeColumnsHandler.createForH2(con, settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the connection to the H2 database.
|
||||||
|
*
|
||||||
|
* @throws SQLException when an SQL error occurs while connecting
|
||||||
|
*/
|
||||||
|
protected void connect() throws SQLException {
|
||||||
|
try {
|
||||||
|
Class.forName("org.h2.Driver");
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
throw new IllegalStateException("Failed to load H2 JDBC class", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug("H2 driver loaded");
|
||||||
|
this.con = DriverManager.getConnection(this.getJdbcUrl(this.dataFolder.getAbsolutePath(), "", this.database));
|
||||||
|
this.columnsHandler = AuthMeColumnsHandler.createForSqlite(con, settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the table if necessary, or adds any missing columns to the table.
|
||||||
|
*
|
||||||
|
* @throws SQLException when an SQL error occurs while initializing the database
|
||||||
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
|
@SuppressWarnings("checkstyle:CyclomaticComplexity")
|
||||||
|
protected void setup() throws SQLException {
|
||||||
|
try (Statement st = con.createStatement()) {
|
||||||
|
// Note: cannot add unique fields later on in SQLite, so we add it on initialization
|
||||||
|
st.executeUpdate("CREATE TABLE IF NOT EXISTS " + tableName + " ("
|
||||||
|
+ col.ID + " INTEGER AUTO_INCREMENT, "
|
||||||
|
+ col.NAME + " VARCHAR(255) NOT NULL UNIQUE, "
|
||||||
|
+ "CONSTRAINT table_const_prim PRIMARY KEY (" + col.ID + "));");
|
||||||
|
|
||||||
|
DatabaseMetaData md = con.getMetaData();
|
||||||
|
|
||||||
|
if (isColumnMissing(md, col.REAL_NAME)) {
|
||||||
|
st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN IF NOT EXISTS "
|
||||||
|
+ col.REAL_NAME + " VARCHAR(255) NOT NULL DEFAULT 'Player';");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isColumnMissing(md, col.PASSWORD)) {
|
||||||
|
st.executeUpdate("ALTER TABLE " + tableName
|
||||||
|
+ " ADD COLUMN IF NOT EXISTS " + col.PASSWORD + " VARCHAR(255) NOT NULL DEFAULT '';");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!col.SALT.isEmpty() && isColumnMissing(md, col.SALT)) {
|
||||||
|
st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN IF NOT EXISTS " + col.SALT + " VARCHAR(255);");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isColumnMissing(md, col.LAST_IP)) {
|
||||||
|
st.executeUpdate("ALTER TABLE " + tableName
|
||||||
|
+ " ADD COLUMN IF NOT EXISTS " + col.LAST_IP + " VARCHAR(40);");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isColumnMissing(md, col.LAST_LOGIN)) {
|
||||||
|
st.executeUpdate("ALTER TABLE " + tableName
|
||||||
|
+ " ADD COLUMN IF NOT EXISTS " + col.LAST_LOGIN + " BIGINT;");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isColumnMissing(md, col.REGISTRATION_IP)) {
|
||||||
|
st.executeUpdate("ALTER TABLE " + tableName
|
||||||
|
+ " ADD COLUMN IF NOT EXISTS " + col.REGISTRATION_IP + " VARCHAR(40);");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isColumnMissing(md, col.REGISTRATION_DATE)) {
|
||||||
|
addRegistrationDateColumn(st);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isColumnMissing(md, col.LASTLOC_X)) {
|
||||||
|
st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN IF NOT EXISTS " + col.LASTLOC_X
|
||||||
|
+ " DOUBLE NOT NULL DEFAULT '0.0';");
|
||||||
|
st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN IF NOT EXISTS " + col.LASTLOC_Y
|
||||||
|
+ " DOUBLE NOT NULL DEFAULT '0.0';");
|
||||||
|
st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN IF NOT EXISTS " + col.LASTLOC_Z
|
||||||
|
+ " DOUBLE NOT NULL DEFAULT '0.0';");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isColumnMissing(md, col.LASTLOC_WORLD)) {
|
||||||
|
st.executeUpdate("ALTER TABLE " + tableName
|
||||||
|
+ " ADD COLUMN IF NOT EXISTS " + col.LASTLOC_WORLD + " VARCHAR(255) NOT NULL DEFAULT 'world';");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isColumnMissing(md, col.LASTLOC_YAW)) {
|
||||||
|
st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN IF NOT EXISTS "
|
||||||
|
+ col.LASTLOC_YAW + " FLOAT;");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isColumnMissing(md, col.LASTLOC_PITCH)) {
|
||||||
|
st.executeUpdate("ALTER TABLE " + tableName + " ADD COLUMN IF NOT EXISTS "
|
||||||
|
+ col.LASTLOC_PITCH + " FLOAT;");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isColumnMissing(md, col.EMAIL)) {
|
||||||
|
st.executeUpdate("ALTER TABLE " + tableName
|
||||||
|
+ " ADD COLUMN IF NOT EXISTS " + col.EMAIL + " VARCHAR_IGNORECASE(255);");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isColumnMissing(md, col.IS_LOGGED)) {
|
||||||
|
st.executeUpdate("ALTER TABLE " + tableName
|
||||||
|
+ " ADD COLUMN IF NOT EXISTS " + col.IS_LOGGED + " INT NOT NULL DEFAULT '0';");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isColumnMissing(md, col.HAS_SESSION)) {
|
||||||
|
st.executeUpdate("ALTER TABLE " + tableName
|
||||||
|
+ " ADD COLUMN IF NOT EXISTS " + col.HAS_SESSION + " INT NOT NULL DEFAULT '0';");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isColumnMissing(md, col.TOTP_KEY)) {
|
||||||
|
st.executeUpdate("ALTER TABLE " + tableName
|
||||||
|
+ " ADD COLUMN IF NOT EXISTS " + col.TOTP_KEY + " VARCHAR(32);");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!col.PLAYER_UUID.isEmpty() && isColumnMissing(md, col.PLAYER_UUID)) {
|
||||||
|
st.executeUpdate("ALTER TABLE " + tableName
|
||||||
|
+ " ADD COLUMN IF NOT EXISTS " + col.PLAYER_UUID + " VARCHAR(36)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logger.info("H2 Setup finished");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a column is missing in the specified table.
|
||||||
|
* @param columnName the name of the column to look for
|
||||||
|
* @return true if the column is missing, false if it exists
|
||||||
|
* @throws SQLException if an error occurs while executing SQL or accessing the result set
|
||||||
|
* @deprecated Not work in H2, it always returns true
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
private boolean isColumnMissing(DatabaseMetaData metaData, String columnName) throws SQLException {
|
||||||
|
String query = "SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ? AND COLUMN_NAME = ?";
|
||||||
|
// try (PreparedStatement preparedStatement = con.prepareStatement(query)) {
|
||||||
|
// preparedStatement.setString(1, tableName);
|
||||||
|
// preparedStatement.setString(2, columnName.toUpperCase());
|
||||||
|
// try (ResultSet rs = preparedStatement.executeQuery()) {
|
||||||
|
// return !rs.next();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reload() {
|
||||||
|
close(con);
|
||||||
|
try {
|
||||||
|
this.connect();
|
||||||
|
this.setup();
|
||||||
|
} catch (SQLException ex) {
|
||||||
|
logger.logException("Error while reloading H2:", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PlayerAuth getAuth(String user) {
|
||||||
|
String sql = "SELECT * FROM " + tableName + " WHERE LOWER(" + col.NAME + ")=LOWER(?);";
|
||||||
|
try (PreparedStatement pst = con.prepareStatement(sql)) {
|
||||||
|
pst.setString(1, user);
|
||||||
|
try (ResultSet rs = pst.executeQuery()) {
|
||||||
|
if (rs.next()) {
|
||||||
|
return buildAuthFromResultSet(rs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (SQLException ex) {
|
||||||
|
logSqlException(ex);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getRecordsToPurge(long until) {
|
||||||
|
Set<String> list = new HashSet<>();
|
||||||
|
String select = "SELECT " + col.NAME + " FROM " + tableName + " WHERE MAX("
|
||||||
|
+ " COALESCE(" + col.LAST_LOGIN + ", 0),"
|
||||||
|
+ " COALESCE(" + col.REGISTRATION_DATE + ", 0)"
|
||||||
|
+ ") < ?;";
|
||||||
|
try (PreparedStatement selectPst = con.prepareStatement(select)) {
|
||||||
|
selectPst.setLong(1, until);
|
||||||
|
try (ResultSet rs = selectPst.executeQuery()) {
|
||||||
|
while (rs.next()) {
|
||||||
|
list.add(rs.getString(col.NAME));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (SQLException ex) {
|
||||||
|
logSqlException(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void purgeRecords(Collection<String> toPurge) {
|
||||||
|
String delete = "DELETE FROM " + tableName + " WHERE " + col.NAME + "=?;";
|
||||||
|
try (PreparedStatement deletePst = con.prepareStatement(delete)) {
|
||||||
|
for (String name : toPurge) {
|
||||||
|
deletePst.setString(1, name.toLowerCase(Locale.ROOT));
|
||||||
|
deletePst.executeUpdate();
|
||||||
|
}
|
||||||
|
} catch (SQLException ex) {
|
||||||
|
logSqlException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean removeAuth(String user) {
|
||||||
|
String sql = "DELETE FROM " + tableName + " WHERE " + col.NAME + "=?;";
|
||||||
|
try (PreparedStatement pst = con.prepareStatement(sql)) {
|
||||||
|
pst.setString(1, user.toLowerCase(Locale.ROOT));
|
||||||
|
pst.executeUpdate();
|
||||||
|
return true;
|
||||||
|
} catch (SQLException ex) {
|
||||||
|
logSqlException(ex);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void closeConnection() {
|
||||||
|
try {
|
||||||
|
if (con != null && !con.isClosed()) {
|
||||||
|
con.close();
|
||||||
|
}
|
||||||
|
} catch (SQLException ex) {
|
||||||
|
logSqlException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataSourceType getType() {
|
||||||
|
return DataSourceType.H2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<PlayerAuth> getAllAuths() {
|
||||||
|
List<PlayerAuth> auths = new ArrayList<>();
|
||||||
|
String sql = "SELECT * FROM " + tableName + ";";
|
||||||
|
try (PreparedStatement pst = con.prepareStatement(sql); ResultSet rs = pst.executeQuery()) {
|
||||||
|
while (rs.next()) {
|
||||||
|
PlayerAuth auth = buildAuthFromResultSet(rs);
|
||||||
|
auths.add(auth);
|
||||||
|
}
|
||||||
|
} catch (SQLException ex) {
|
||||||
|
logSqlException(ex);
|
||||||
|
}
|
||||||
|
return auths;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getLoggedPlayersWithEmptyMail() {
|
||||||
|
List<String> players = new ArrayList<>();
|
||||||
|
String sql = "SELECT " + col.REAL_NAME + " FROM " + tableName + " WHERE " + col.IS_LOGGED + " = 1"
|
||||||
|
+ " AND (" + col.EMAIL + " = 'your@email.com' OR " + col.EMAIL + " IS NULL);";
|
||||||
|
try (Statement st = con.createStatement(); ResultSet rs = st.executeQuery(sql)) {
|
||||||
|
while (rs.next()) {
|
||||||
|
players.add(rs.getString(1));
|
||||||
|
}
|
||||||
|
} catch (SQLException ex) {
|
||||||
|
logSqlException(ex);
|
||||||
|
}
|
||||||
|
return players;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<PlayerAuth> getRecentlyLoggedInPlayers() {
|
||||||
|
List<PlayerAuth> players = new ArrayList<>();
|
||||||
|
String sql = "SELECT * FROM " + tableName + " ORDER BY " + col.LAST_LOGIN + " DESC LIMIT 10;";
|
||||||
|
try (Statement st = con.createStatement(); ResultSet rs = st.executeQuery(sql)) {
|
||||||
|
while (rs.next()) {
|
||||||
|
players.add(buildAuthFromResultSet(rs));
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
logSqlException(e);
|
||||||
|
}
|
||||||
|
return players;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setTotpKey(String user, String totpKey) {
|
||||||
|
String sql = "UPDATE " + tableName + " SET " + col.TOTP_KEY + " = ? WHERE " + col.NAME + " = ?";
|
||||||
|
try (PreparedStatement pst = con.prepareStatement(sql)) {
|
||||||
|
pst.setString(1, totpKey);
|
||||||
|
pst.setString(2, user.toLowerCase(Locale.ROOT));
|
||||||
|
pst.executeUpdate();
|
||||||
|
return true;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
logSqlException(e);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private PlayerAuth buildAuthFromResultSet(ResultSet row) throws SQLException {
|
||||||
|
String salt = !col.SALT.isEmpty() ? row.getString(col.SALT) : null;
|
||||||
|
|
||||||
|
return PlayerAuth.builder()
|
||||||
|
.name(row.getString(col.NAME))
|
||||||
|
.email(row.getString(col.EMAIL))
|
||||||
|
.realName(row.getString(col.REAL_NAME))
|
||||||
|
.password(row.getString(col.PASSWORD), salt)
|
||||||
|
.totpKey(row.getString(col.TOTP_KEY))
|
||||||
|
.lastLogin(getNullableLong(row, col.LAST_LOGIN))
|
||||||
|
.lastIp(row.getString(col.LAST_IP))
|
||||||
|
.registrationDate(row.getLong(col.REGISTRATION_DATE))
|
||||||
|
.registrationIp(row.getString(col.REGISTRATION_IP))
|
||||||
|
.locX(row.getDouble(col.LASTLOC_X))
|
||||||
|
.locY(row.getDouble(col.LASTLOC_Y))
|
||||||
|
.locZ(row.getDouble(col.LASTLOC_Z))
|
||||||
|
.locWorld(row.getString(col.LASTLOC_WORLD))
|
||||||
|
.locYaw(row.getFloat(col.LASTLOC_YAW))
|
||||||
|
.locPitch(row.getFloat(col.LASTLOC_PITCH))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the column for registration date and sets all entries to the current timestamp.
|
||||||
|
* We do so in order to avoid issues with purging, where entries with 0 / NULL might get
|
||||||
|
* purged immediately on startup otherwise.
|
||||||
|
*
|
||||||
|
* @param st Statement object to the database
|
||||||
|
*/
|
||||||
|
private void addRegistrationDateColumn(Statement st) throws SQLException {
|
||||||
|
int affect = st.executeUpdate("ALTER TABLE " + tableName
|
||||||
|
+ " ADD COLUMN IF NOT EXISTS " + col.REGISTRATION_DATE + " BIGINT NOT NULL DEFAULT '0';");
|
||||||
|
if (affect > 0) {
|
||||||
|
long currentTimestamp = System.currentTimeMillis();
|
||||||
|
int updatedRows = st.executeUpdate(String.format("UPDATE %s SET %s = %d;",
|
||||||
|
tableName, col.REGISTRATION_DATE, currentTimestamp));
|
||||||
|
logger.info("Created column '" + col.REGISTRATION_DATE + "' and set the current timestamp, "
|
||||||
|
+ currentTimestamp + ", to all " + updatedRows + " rows");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
String getJdbcUrl(String dataPath, String ignored, String database) {
|
||||||
|
return "jdbc:h2:" + dataPath + File.separator + database;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void close(Connection con) {
|
||||||
|
if (con != null) {
|
||||||
|
try {
|
||||||
|
con.close();
|
||||||
|
} catch (SQLException ex) {
|
||||||
|
logSqlException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -41,6 +41,7 @@ public class MySQL extends AbstractSqlDataSource {
|
|||||||
private boolean useSsl;
|
private boolean useSsl;
|
||||||
private boolean serverCertificateVerification;
|
private boolean serverCertificateVerification;
|
||||||
private boolean allowPublicKeyRetrieval;
|
private boolean allowPublicKeyRetrieval;
|
||||||
|
private String mariaDbSslMode;
|
||||||
private String host;
|
private String host;
|
||||||
private String port;
|
private String port;
|
||||||
private String username;
|
private String username;
|
||||||
@@ -121,6 +122,7 @@ public class MySQL extends AbstractSqlDataSource {
|
|||||||
this.useSsl = settings.getProperty(DatabaseSettings.MYSQL_USE_SSL);
|
this.useSsl = settings.getProperty(DatabaseSettings.MYSQL_USE_SSL);
|
||||||
this.serverCertificateVerification = settings.getProperty(DatabaseSettings.MYSQL_CHECK_SERVER_CERTIFICATE);
|
this.serverCertificateVerification = settings.getProperty(DatabaseSettings.MYSQL_CHECK_SERVER_CERTIFICATE);
|
||||||
this.allowPublicKeyRetrieval = settings.getProperty(DatabaseSettings.MYSQL_ALLOW_PUBLIC_KEY_RETRIEVAL);
|
this.allowPublicKeyRetrieval = settings.getProperty(DatabaseSettings.MYSQL_ALLOW_PUBLIC_KEY_RETRIEVAL);
|
||||||
|
this.mariaDbSslMode = settings.getProperty(DatabaseSettings.MARIADB_SSL_MODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -145,12 +147,19 @@ public class MySQL extends AbstractSqlDataSource {
|
|||||||
ds.setDriverClassName(this.getDriverClassName());
|
ds.setDriverClassName(this.getDriverClassName());
|
||||||
|
|
||||||
// Request mysql over SSL
|
// Request mysql over SSL
|
||||||
|
if (this instanceof MariaDB) {
|
||||||
|
ds.addDataSourceProperty("sslMode", mariaDbSslMode);
|
||||||
|
} else {
|
||||||
ds.addDataSourceProperty("useSSL", String.valueOf(useSsl));
|
ds.addDataSourceProperty("useSSL", String.valueOf(useSsl));
|
||||||
|
|
||||||
// Disabling server certificate verification on need
|
// Disabling server certificate verification on need
|
||||||
if (!serverCertificateVerification) {
|
if (!serverCertificateVerification) {
|
||||||
ds.addDataSourceProperty("verifyServerCertificate", String.valueOf(false));
|
ds.addDataSourceProperty("verifyServerCertificate", String.valueOf(false));
|
||||||
} // Disabling server certificate verification on need
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Disabling server certificate verification on need
|
||||||
if (allowPublicKeyRetrieval) {
|
if (allowPublicKeyRetrieval) {
|
||||||
ds.addDataSourceProperty("allowPublicKeyRetrieval", String.valueOf(true));
|
ds.addDataSourceProperty("allowPublicKeyRetrieval", String.valueOf(true));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,6 +51,26 @@ public final class AuthMeColumnsHandler {
|
|||||||
return new AuthMeColumnsHandler(sqlColHandler);
|
return new AuthMeColumnsHandler(sqlColHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a column handler for H2.
|
||||||
|
*
|
||||||
|
* @param connection the connection to the database
|
||||||
|
* @param settings plugin settings
|
||||||
|
* @return created column handler
|
||||||
|
*/
|
||||||
|
public static AuthMeColumnsHandler createForH2(Connection connection, Settings settings) {
|
||||||
|
ColumnContext columnContext = new ColumnContext(settings, false);
|
||||||
|
String tableName = settings.getProperty(DatabaseSettings.MYSQL_TABLE);
|
||||||
|
String nameColumn = settings.getProperty(DatabaseSettings.MYSQL_COL_NAME);
|
||||||
|
|
||||||
|
SqlColumnsHandler<ColumnContext, String> sqlColHandler = new SqlColumnsHandler<>(
|
||||||
|
forSingleConnection(connection, tableName, nameColumn, columnContext)
|
||||||
|
.setPredicateSqlGenerator(new PredicateSqlGenerator<>(columnContext, false))
|
||||||
|
);
|
||||||
|
return new AuthMeColumnsHandler(sqlColHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a column handler for MySQL.
|
* Creates a column handler for MySQL.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package fr.xephi.authme.datasource.converter;
|
||||||
|
|
||||||
|
import fr.xephi.authme.datasource.DataSource;
|
||||||
|
import fr.xephi.authme.datasource.DataSourceType;
|
||||||
|
import fr.xephi.authme.datasource.H2;
|
||||||
|
import fr.xephi.authme.initialization.DataFolder;
|
||||||
|
import fr.xephi.authme.settings.Settings;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import java.io.File;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts H2 to SQLite.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class H2ToSqlite extends AbstractDataSourceConverter<H2>{
|
||||||
|
|
||||||
|
private final Settings settings;
|
||||||
|
private final File dataFolder;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
H2ToSqlite(Settings settings, DataSource dataSource, @DataFolder File dataFolder) {
|
||||||
|
super(dataSource, DataSourceType.SQLITE);
|
||||||
|
this.settings = settings;
|
||||||
|
this.dataFolder = dataFolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected H2 getSource() throws SQLException {
|
||||||
|
return new H2(settings, dataFolder);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
package fr.xephi.authme.datasource.converter;
|
|
||||||
|
|
||||||
import fr.xephi.authme.ConsoleLogger;
|
|
||||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
|
||||||
import fr.xephi.authme.datasource.DataSource;
|
|
||||||
import fr.xephi.authme.initialization.DataFolder;
|
|
||||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
|
||||||
import fr.xephi.authme.security.PasswordSecurity;
|
|
||||||
import fr.xephi.authme.security.crypts.HashedPassword;
|
|
||||||
import fr.xephi.authme.settings.Settings;
|
|
||||||
import fr.xephi.authme.settings.properties.ConverterSettings;
|
|
||||||
import fr.xephi.authme.util.Utils;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileReader;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Xephi59
|
|
||||||
*/
|
|
||||||
public class RakamakConverter implements Converter {
|
|
||||||
|
|
||||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(RakamakConverter.class);
|
|
||||||
private final DataSource database;
|
|
||||||
private final Settings settings;
|
|
||||||
private final File pluginFolder;
|
|
||||||
private final PasswordSecurity passwordSecurity;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
RakamakConverter(@DataFolder File dataFolder, DataSource dataSource, Settings settings,
|
|
||||||
PasswordSecurity passwordSecurity) {
|
|
||||||
this.database = dataSource;
|
|
||||||
this.settings = settings;
|
|
||||||
this.pluginFolder = dataFolder;
|
|
||||||
this.passwordSecurity = passwordSecurity;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
//TODO ljacqu 20151229: Restructure this into smaller portions
|
|
||||||
public void execute(CommandSender sender) {
|
|
||||||
boolean useIp = settings.getProperty(ConverterSettings.RAKAMAK_USE_IP);
|
|
||||||
String fileName = settings.getProperty(ConverterSettings.RAKAMAK_FILE_NAME);
|
|
||||||
String ipFileName = settings.getProperty(ConverterSettings.RAKAMAK_IP_FILE_NAME);
|
|
||||||
File source = new File(pluginFolder, fileName);
|
|
||||||
File ipFiles = new File(pluginFolder, ipFileName);
|
|
||||||
Map<String, String> playerIp = new HashMap<>();
|
|
||||||
Map<String, HashedPassword> playerPassword = new HashMap<>();
|
|
||||||
try {
|
|
||||||
BufferedReader ipFile = new BufferedReader(new FileReader(ipFiles));
|
|
||||||
String line;
|
|
||||||
if (useIp) {
|
|
||||||
String tempLine;
|
|
||||||
while ((tempLine = ipFile.readLine()) != null) {
|
|
||||||
if (tempLine.contains("=")) {
|
|
||||||
String[] args = tempLine.split("=");
|
|
||||||
playerIp.put(args[0], args[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ipFile.close();
|
|
||||||
|
|
||||||
BufferedReader users = new BufferedReader(new FileReader(source));
|
|
||||||
while ((line = users.readLine()) != null) {
|
|
||||||
if (line.contains("=")) {
|
|
||||||
String[] arguments = line.split("=");
|
|
||||||
HashedPassword hashedPassword = passwordSecurity.computeHash(arguments[1], arguments[0]);
|
|
||||||
playerPassword.put(arguments[0], hashedPassword);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
users.close();
|
|
||||||
for (Entry<String, HashedPassword> m : playerPassword.entrySet()) {
|
|
||||||
String playerName = m.getKey();
|
|
||||||
HashedPassword psw = playerPassword.get(playerName);
|
|
||||||
String ip = playerIp.get(playerName);
|
|
||||||
PlayerAuth auth = PlayerAuth.builder()
|
|
||||||
.name(playerName)
|
|
||||||
.realName(playerName)
|
|
||||||
.lastIp(ip)
|
|
||||||
.password(psw)
|
|
||||||
.build();
|
|
||||||
database.saveAuth(auth);
|
|
||||||
database.updateSession(auth);
|
|
||||||
}
|
|
||||||
Utils.logAndSendMessage(sender, "Rakamak database has been imported successfully");
|
|
||||||
} catch (IOException ex) {
|
|
||||||
logger.logException("Can't open the rakamak database file! Does it exist?", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package fr.xephi.authme.datasource.converter;
|
||||||
|
|
||||||
|
import fr.xephi.authme.datasource.DataSource;
|
||||||
|
import fr.xephi.authme.datasource.DataSourceType;
|
||||||
|
import fr.xephi.authme.datasource.SQLite;
|
||||||
|
import fr.xephi.authme.initialization.DataFolder;
|
||||||
|
import fr.xephi.authme.settings.Settings;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import java.io.File;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts SQLite to H2
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class SqliteToH2 extends AbstractDataSourceConverter<SQLite>{
|
||||||
|
|
||||||
|
private final Settings settings;
|
||||||
|
private final File dataFolder;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
SqliteToH2(Settings settings, DataSource dataSource, @DataFolder File dataFolder) {
|
||||||
|
super(dataSource, DataSourceType.H2);
|
||||||
|
this.settings = settings;
|
||||||
|
this.dataFolder = dataFolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected SQLite getSource() throws SQLException {
|
||||||
|
return new SQLite(settings, dataFolder);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
package fr.xephi.authme.datasource.converter;
|
|
||||||
|
|
||||||
import fr.xephi.authme.ConsoleLogger;
|
|
||||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
|
||||||
import fr.xephi.authme.datasource.DataSource;
|
|
||||||
import fr.xephi.authme.initialization.DataFolder;
|
|
||||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.OfflinePlayer;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Scanner;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import static fr.xephi.authme.util.FileUtils.makePath;
|
|
||||||
|
|
||||||
public class VAuthConverter implements Converter {
|
|
||||||
|
|
||||||
private final ConsoleLogger logger = ConsoleLoggerFactory.get(VAuthConverter.class);
|
|
||||||
private final DataSource dataSource;
|
|
||||||
private final File vAuthPasswordsFile;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
VAuthConverter(@DataFolder File dataFolder, DataSource dataSource) {
|
|
||||||
vAuthPasswordsFile = new File(dataFolder.getParent(), makePath("vAuth", "passwords.yml"));
|
|
||||||
this.dataSource = dataSource;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(CommandSender sender) {
|
|
||||||
try (Scanner scanner = new Scanner(vAuthPasswordsFile)) {
|
|
||||||
while (scanner.hasNextLine()) {
|
|
||||||
String line = scanner.nextLine();
|
|
||||||
String name = line.split(": ")[0];
|
|
||||||
String password = line.split(": ")[1];
|
|
||||||
PlayerAuth auth;
|
|
||||||
if (isUuidInstance(password)) {
|
|
||||||
String pname;
|
|
||||||
try {
|
|
||||||
pname = Bukkit.getOfflinePlayer(UUID.fromString(name)).getName();
|
|
||||||
} catch (Exception | NoSuchMethodError e) {
|
|
||||||
pname = getName(UUID.fromString(name));
|
|
||||||
}
|
|
||||||
if (pname == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
auth = PlayerAuth.builder()
|
|
||||||
.name(pname.toLowerCase(Locale.ROOT))
|
|
||||||
.realName(pname)
|
|
||||||
.password(password, null).build();
|
|
||||||
} else {
|
|
||||||
auth = PlayerAuth.builder()
|
|
||||||
.name(name.toLowerCase(Locale.ROOT))
|
|
||||||
.realName(name)
|
|
||||||
.password(password, null).build();
|
|
||||||
}
|
|
||||||
dataSource.saveAuth(auth);
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.logException("Error while trying to import some vAuth data", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isUuidInstance(String s) {
|
|
||||||
return s.length() > 8 && s.charAt(8) == '-';
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getName(UUID uuid) {
|
|
||||||
for (OfflinePlayer op : Bukkit.getOfflinePlayers()) {
|
|
||||||
if (op.getUniqueId().compareTo(uuid) == 0) {
|
|
||||||
return op.getName();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
package fr.xephi.authme.initialization;
|
package fr.xephi.authme.initialization;
|
||||||
|
|
||||||
|
import com.alessiodp.libby.Library;
|
||||||
import fr.xephi.authme.ConsoleLogger;
|
import fr.xephi.authme.ConsoleLogger;
|
||||||
import fr.xephi.authme.data.auth.PlayerCache;
|
import fr.xephi.authme.data.auth.PlayerCache;
|
||||||
import fr.xephi.authme.datasource.CacheDataSource;
|
import fr.xephi.authme.datasource.CacheDataSource;
|
||||||
import fr.xephi.authme.datasource.DataSource;
|
import fr.xephi.authme.datasource.DataSource;
|
||||||
import fr.xephi.authme.datasource.DataSourceType;
|
import fr.xephi.authme.datasource.DataSourceType;
|
||||||
|
import fr.xephi.authme.datasource.H2;
|
||||||
import fr.xephi.authme.datasource.MariaDB;
|
import fr.xephi.authme.datasource.MariaDB;
|
||||||
import fr.xephi.authme.datasource.MySQL;
|
import fr.xephi.authme.datasource.MySQL;
|
||||||
import fr.xephi.authme.datasource.PostgreSqlDataSource;
|
import fr.xephi.authme.datasource.PostgreSqlDataSource;
|
||||||
@@ -20,6 +22,8 @@ import javax.inject.Provider;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
import static fr.xephi.authme.AuthMe.libraryManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the AuthMe data source.
|
* Creates the AuthMe data source.
|
||||||
*/
|
*/
|
||||||
@@ -76,6 +80,16 @@ public class DataSourceProvider implements Provider<DataSource> {
|
|||||||
case SQLITE:
|
case SQLITE:
|
||||||
dataSource = new SQLite(settings, dataFolder);
|
dataSource = new SQLite(settings, dataFolder);
|
||||||
break;
|
break;
|
||||||
|
case H2:
|
||||||
|
Library h2 = Library.builder()
|
||||||
|
.groupId("com.h2database")
|
||||||
|
.artifactId("h2")
|
||||||
|
.version("2.2.224")
|
||||||
|
.build();
|
||||||
|
libraryManager.addMavenCentral();
|
||||||
|
libraryManager.loadLibrary(h2);
|
||||||
|
dataSource = new H2(settings, dataFolder);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new UnsupportedOperationException("Unknown data source type '" + dataSourceType + "'");
|
throw new UnsupportedOperationException("Unknown data source type '" + dataSourceType + "'");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package fr.xephi.authme.initialization;
|
package fr.xephi.authme.initialization;
|
||||||
|
|
||||||
|
import com.github.Anon8281.universalScheduler.UniversalRunnable;
|
||||||
import fr.xephi.authme.AuthMe;
|
import fr.xephi.authme.AuthMe;
|
||||||
import fr.xephi.authme.ConsoleLogger;
|
import fr.xephi.authme.ConsoleLogger;
|
||||||
import fr.xephi.authme.datasource.DataSource;
|
import fr.xephi.authme.datasource.DataSource;
|
||||||
@@ -18,7 +19,6 @@ import org.bstats.bukkit.Metrics;
|
|||||||
import org.bstats.charts.SimplePie;
|
import org.bstats.charts.SimplePie;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.scheduler.BukkitRunnable;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -96,7 +96,7 @@ public class OnStartupTasks {
|
|||||||
if (!settings.getProperty(RECALL_PLAYERS)) {
|
if (!settings.getProperty(RECALL_PLAYERS)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bukkitService.runTaskTimerAsynchronously(new BukkitRunnable() {
|
bukkitService.runTaskTimerAsynchronously(new UniversalRunnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
List<String> loggedPlayersWithEmptyMail = dataSource.getLoggedPlayersWithEmptyMail();
|
List<String> loggedPlayersWithEmptyMail = dataSource.getLoggedPlayersWithEmptyMail();
|
||||||
@@ -109,6 +109,6 @@ public class OnStartupTasks {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, 1, TICKS_PER_MINUTE * settings.getProperty(EmailSettings.DELAY_RECALL));
|
}, 1, (long) TICKS_PER_MINUTE * settings.getProperty(EmailSettings.DELAY_RECALL));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,8 @@
|
|||||||
package fr.xephi.authme.initialization;
|
package fr.xephi.authme.initialization;
|
||||||
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.github.Anon8281.universalScheduler.scheduling.schedulers.TaskScheduler;
|
||||||
import fr.xephi.authme.AuthMe;
|
import fr.xephi.authme.AuthMe;
|
||||||
import fr.xephi.authme.datasource.DataSource;
|
import fr.xephi.authme.datasource.DataSource;
|
||||||
import org.bukkit.scheduler.BukkitScheduler;
|
|
||||||
import org.bukkit.scheduler.BukkitWorker;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Waits for asynchronous tasks to complete before closing the data source
|
* Waits for asynchronous tasks to complete before closing the data source
|
||||||
@@ -18,78 +10,24 @@ import java.util.logging.Logger;
|
|||||||
*/
|
*/
|
||||||
public class TaskCloser implements Runnable {
|
public class TaskCloser implements Runnable {
|
||||||
|
|
||||||
private final BukkitScheduler scheduler;
|
private final TaskScheduler scheduler;
|
||||||
private final Logger logger;
|
|
||||||
private final AuthMe plugin;
|
|
||||||
private final DataSource dataSource;
|
private final DataSource dataSource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
*
|
*
|
||||||
* @param plugin the plugin instance
|
|
||||||
* @param dataSource the data source (nullable)
|
* @param dataSource the data source (nullable)
|
||||||
*/
|
*/
|
||||||
public TaskCloser(AuthMe plugin, DataSource dataSource) {
|
public TaskCloser(DataSource dataSource) {
|
||||||
this.scheduler = plugin.getServer().getScheduler();
|
this.scheduler = AuthMe.getScheduler();
|
||||||
this.logger = plugin.getLogger();
|
|
||||||
this.plugin = plugin;
|
|
||||||
this.dataSource = dataSource;
|
this.dataSource = dataSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
List<Integer> pendingTasks = getPendingTasks();
|
scheduler.cancelTasks();
|
||||||
logger.log(Level.INFO, "Waiting for {0} tasks to finish", pendingTasks.size());
|
|
||||||
int progress = 0;
|
|
||||||
|
|
||||||
//one minute + some time checking the running state
|
|
||||||
int tries = 60;
|
|
||||||
while (!pendingTasks.isEmpty()) {
|
|
||||||
if (tries <= 0) {
|
|
||||||
logger.log(Level.INFO, "Async tasks times out after to many tries {0}", pendingTasks);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
sleep();
|
|
||||||
} catch (InterruptedException ignored) {
|
|
||||||
Thread.currentThread().interrupt();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Iterator<Integer> iterator = pendingTasks.iterator(); iterator.hasNext(); ) {
|
|
||||||
int taskId = iterator.next();
|
|
||||||
if (!scheduler.isCurrentlyRunning(taskId)) {
|
|
||||||
iterator.remove();
|
|
||||||
progress++;
|
|
||||||
logger.log(Level.INFO, "Progress: {0} / {1}", new Object[]{progress, pendingTasks.size()});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tries--;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dataSource != null) {
|
if (dataSource != null) {
|
||||||
dataSource.closeConnection();
|
dataSource.closeConnection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Makes the current thread sleep for one second. */
|
|
||||||
@VisibleForTesting
|
|
||||||
void sleep() throws InterruptedException {
|
|
||||||
Thread.sleep(1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<Integer> getPendingTasks() {
|
|
||||||
List<Integer> pendingTasks = new ArrayList<>();
|
|
||||||
//returns only the async tasks
|
|
||||||
for (BukkitWorker pendingTask : scheduler.getActiveWorkers()) {
|
|
||||||
if (pendingTask.getOwner().equals(plugin)
|
|
||||||
//it's not a periodic task
|
|
||||||
&& !scheduler.isQueued(pendingTask.getTaskId())) {
|
|
||||||
pendingTasks.add(pendingTask.getTaskId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return pendingTasks;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package fr.xephi.authme.listener;
|
||||||
|
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.EventPriority;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.block.BlockDispenseEvent;
|
||||||
|
|
||||||
|
//This fix is only for Minecraft 1.13-
|
||||||
|
public class AdvancedShulkerFixListener implements Listener {
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
|
||||||
|
public void onDispenserActivate(BlockDispenseEvent event) {
|
||||||
|
Block block = event.getBlock();
|
||||||
|
|
||||||
|
if (block.getY() <= 0 || block.getY() >= block.getWorld().getMaxHeight() - 1) {
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
package fr.xephi.authme.listener;
|
||||||
|
/* Inspired by DongShaoNB/BedrockPlayerSupport **/
|
||||||
|
|
||||||
|
import fr.xephi.authme.AuthMe;
|
||||||
|
import fr.xephi.authme.api.v3.AuthMeApi;
|
||||||
|
import fr.xephi.authme.message.MessageKey;
|
||||||
|
import fr.xephi.authme.message.Messages;
|
||||||
|
import fr.xephi.authme.service.BukkitService;
|
||||||
|
import fr.xephi.authme.settings.Settings;
|
||||||
|
import fr.xephi.authme.settings.properties.HooksSettings;
|
||||||
|
import fr.xephi.authme.settings.properties.SecuritySettings;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.EventPriority;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.player.PlayerJoinEvent;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import static org.bukkit.Bukkit.getServer;
|
||||||
|
|
||||||
|
public class BedrockAutoLoginListener implements Listener {
|
||||||
|
private final AuthMeApi authmeApi = AuthMeApi.getInstance();
|
||||||
|
@Inject
|
||||||
|
private BukkitService bukkitService;
|
||||||
|
@Inject
|
||||||
|
private AuthMe plugin;
|
||||||
|
@Inject
|
||||||
|
private Messages messages;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private Settings settings;
|
||||||
|
|
||||||
|
public BedrockAutoLoginListener() {
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isBedrockPlayer(UUID uuid) {
|
||||||
|
return settings.getProperty(HooksSettings.HOOK_FLOODGATE_PLAYER) && settings.getProperty(SecuritySettings.FORCE_LOGIN_BEDROCK) && org.geysermc.floodgate.api.FloodgateApi.getInstance().isFloodgateId(uuid) && getServer().getPluginManager().getPlugin("floodgate") != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.MONITOR)
|
||||||
|
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||||
|
Player player = event.getPlayer();
|
||||||
|
String name = event.getPlayer().getName();
|
||||||
|
UUID uuid = event.getPlayer().getUniqueId();
|
||||||
|
bukkitService.runTaskLater(player, () -> {
|
||||||
|
if (isBedrockPlayer(uuid) && !authmeApi.isAuthenticated(player) && authmeApi.isRegistered(name)) {
|
||||||
|
authmeApi.forceLogin(player, true);
|
||||||
|
messages.send(player, MessageKey.BEDROCK_AUTO_LOGGED_IN);
|
||||||
|
}
|
||||||
|
},20L);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package fr.xephi.authme.listener;
|
||||||
|
//Prevent Ghost Players
|
||||||
|
|
||||||
|
import fr.xephi.authme.message.MessageKey;
|
||||||
|
import fr.xephi.authme.service.CommonService;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.player.PlayerJoinEvent;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
|
public class DoubleLoginFixListener implements Listener {
|
||||||
|
@Inject
|
||||||
|
private CommonService service;
|
||||||
|
|
||||||
|
public DoubleLoginFixListener() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||||
|
Collection<? extends Player> PlayerList = Bukkit.getServer().getOnlinePlayers();
|
||||||
|
HashSet<String> PlayerSet = new HashSet<String>();
|
||||||
|
for (Player ep : PlayerList) {
|
||||||
|
if (PlayerSet.contains(ep.getName().toLowerCase())) {
|
||||||
|
ep.kickPlayer(service.retrieveSingleMessage(ep.getPlayer(), MessageKey.DOUBLE_LOGIN_FIX));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
PlayerSet.add(ep.getName().toLowerCase());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,34 +1,23 @@
|
|||||||
package fr.xephi.authme.listener;
|
package fr.xephi.authme.listener;
|
||||||
|
|
||||||
import fr.xephi.authme.AuthMe;
|
|
||||||
import fr.xephi.authme.api.v3.AuthMeApi;
|
|
||||||
import fr.xephi.authme.data.auth.PlayerCache;
|
import fr.xephi.authme.data.auth.PlayerCache;
|
||||||
import fr.xephi.authme.datasource.DataSource;
|
import fr.xephi.authme.datasource.DataSource;
|
||||||
import fr.xephi.authme.initialization.SettingsDependent;
|
import fr.xephi.authme.initialization.SettingsDependent;
|
||||||
import fr.xephi.authme.service.ValidationService;
|
import fr.xephi.authme.service.ValidationService;
|
||||||
import fr.xephi.authme.settings.Settings;
|
import fr.xephi.authme.settings.Settings;
|
||||||
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
||||||
import fr.xephi.authme.settings.properties.SecuritySettings;
|
|
||||||
import fr.xephi.authme.util.PlayerUtils;
|
import fr.xephi.authme.util.PlayerUtils;
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
|
||||||
import org.bukkit.event.entity.EntityEvent;
|
import org.bukkit.event.entity.EntityEvent;
|
||||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
|
||||||
import org.bukkit.event.inventory.InventoryOpenEvent;
|
|
||||||
import org.bukkit.event.player.PlayerEvent;
|
import org.bukkit.event.player.PlayerEvent;
|
||||||
import org.bukkit.inventory.Inventory;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service class for the AuthMe listeners to determine whether an event should be canceled.
|
* Service class for the AuthMe listeners to determine whether an event should be canceled.
|
||||||
*/
|
*/
|
||||||
class ListenerService implements SettingsDependent {
|
class ListenerService implements SettingsDependent {
|
||||||
private final AuthMeApi authmeApi = AuthMeApi.getInstance();
|
|
||||||
private final DataSource dataSource;
|
private final DataSource dataSource;
|
||||||
private final PlayerCache playerCache;
|
private final PlayerCache playerCache;
|
||||||
private final ValidationService validationService;
|
private final ValidationService validationService;
|
||||||
@@ -86,19 +75,9 @@ class ListenerService implements SettingsDependent {
|
|||||||
* @param player the player to verify
|
* @param player the player to verify
|
||||||
* @return true if the associated event should be canceled, false otherwise
|
* @return true if the associated event should be canceled, false otherwise
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public boolean shouldCancelEvent(Player player) {
|
public boolean shouldCancelEvent(Player player) {
|
||||||
|
|
||||||
return player != null && !checkAuth(player.getName()) && !PlayerUtils.isNpc(player);
|
return player != null && !checkAuth(player.getName()) && !PlayerUtils.isNpc(player);
|
||||||
}
|
}
|
||||||
public boolean shouldCancelInvEvent(Player player) {
|
|
||||||
try {
|
|
||||||
return !AuthMe.GUIEnabled || authmeApi.isRegistered(player.getName()) || RegisterListener.closeReasonMap.containsKey(player)/* || !player.getOpenInventory().getTitle().equals("请验证你是真人")*/;
|
|
||||||
} catch (Exception e) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reload(Settings settings) {
|
public void reload(Settings settings) {
|
||||||
isRegistrationForced = settings.getProperty(RegistrationSettings.FORCE);
|
isRegistrationForced = settings.getProperty(RegistrationSettings.FORCE);
|
||||||
|
|||||||
@@ -0,0 +1,118 @@
|
|||||||
|
package fr.xephi.authme.listener;
|
||||||
|
|
||||||
|
import fr.xephi.authme.AuthMe;
|
||||||
|
import fr.xephi.authme.api.v3.AuthMeApi;
|
||||||
|
import fr.xephi.authme.message.MessageKey;
|
||||||
|
import fr.xephi.authme.message.Messages;
|
||||||
|
import fr.xephi.authme.settings.Settings;
|
||||||
|
import fr.xephi.authme.settings.properties.SecuritySettings;
|
||||||
|
import fr.xephi.authme.util.TeleportUtils;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.block.BlockFace;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.player.PlayerJoinEvent;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
|
||||||
|
public class LoginLocationFixListener implements Listener {
|
||||||
|
@Inject
|
||||||
|
private AuthMe plugin;
|
||||||
|
@Inject
|
||||||
|
private Messages messages;
|
||||||
|
@Inject
|
||||||
|
private Settings settings;
|
||||||
|
private final AuthMeApi authmeApi = AuthMeApi.getInstance();
|
||||||
|
|
||||||
|
public LoginLocationFixListener() {
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Material materialPortal = Material.matchMaterial("PORTAL");
|
||||||
|
|
||||||
|
private static boolean isAvailable; // false: unchecked/method not available true: method is available
|
||||||
|
BlockFace[] faces = {BlockFace.WEST, BlockFace.EAST, BlockFace.NORTH, BlockFace.SOUTH, BlockFace.SOUTH_EAST, BlockFace.SOUTH_WEST, BlockFace.NORTH_EAST, BlockFace.NORTH_WEST};
|
||||||
|
|
||||||
|
static {
|
||||||
|
if (materialPortal == null) {
|
||||||
|
materialPortal = Material.matchMaterial("PORTAL_BLOCK");
|
||||||
|
if (materialPortal == null) {
|
||||||
|
materialPortal = Material.matchMaterial("NETHER_PORTAL");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Method getMinHeightMethod = World.class.getMethod("getMinHeight");
|
||||||
|
isAvailable = true;
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
isAvailable = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getMinHeight(World world) {
|
||||||
|
//This keeps compatibility of 1.16.x and lower
|
||||||
|
if (isAvailable) {
|
||||||
|
return world.getMinHeight();
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||||
|
Player player = event.getPlayer();
|
||||||
|
Location JoinLocation = player.getLocation();
|
||||||
|
if (settings.getProperty(SecuritySettings.LOGIN_LOC_FIX_SUB_PORTAL)) {
|
||||||
|
if (!JoinLocation.getBlock().getType().equals(materialPortal) && !JoinLocation.getBlock().getRelative(BlockFace.UP).getType().equals(materialPortal)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Block JoinBlock = JoinLocation.getBlock();
|
||||||
|
boolean solved = false;
|
||||||
|
for (BlockFace face : faces) {
|
||||||
|
if (JoinBlock.getRelative(face).getType().equals(Material.AIR) && JoinBlock.getRelative(face).getRelative(BlockFace.UP).getType().equals(Material.AIR)) {
|
||||||
|
TeleportUtils.teleport(player, JoinBlock.getRelative(face).getLocation().add(0.5, 0.1, 0.5));
|
||||||
|
solved = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!solved) {
|
||||||
|
JoinBlock.getRelative(BlockFace.UP).breakNaturally();
|
||||||
|
JoinBlock.breakNaturally();
|
||||||
|
}
|
||||||
|
messages.send(player, MessageKey.LOCATION_FIX_PORTAL);
|
||||||
|
}
|
||||||
|
if (settings.getProperty(SecuritySettings.LOGIN_LOC_FIX_SUB_UNDERGROUND)) {
|
||||||
|
Material UpType = JoinLocation.getBlock().getRelative(BlockFace.UP).getType();
|
||||||
|
World world = player.getWorld();
|
||||||
|
int MaxHeight = world.getMaxHeight();
|
||||||
|
int MinHeight = getMinHeight(world);
|
||||||
|
if (!UpType.isOccluding() && !UpType.equals(Material.LAVA)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (int i = MinHeight; i <= MaxHeight; i++) {
|
||||||
|
JoinLocation.setY(i);
|
||||||
|
Block JoinBlock = JoinLocation.getBlock();
|
||||||
|
if ((JoinBlock.getRelative(BlockFace.DOWN).getType().isBlock())
|
||||||
|
&& JoinBlock.getType().equals(Material.AIR)
|
||||||
|
&& JoinBlock.getRelative(BlockFace.UP).getType().equals(Material.AIR)) {
|
||||||
|
if (JoinBlock.getRelative(BlockFace.DOWN).getType().equals(Material.LAVA)) {
|
||||||
|
JoinBlock.getRelative(BlockFace.DOWN).setType(Material.DIRT);
|
||||||
|
}
|
||||||
|
TeleportUtils.teleport(player, JoinBlock.getLocation().add(0.5, 0.1, 0.5));
|
||||||
|
messages.send(player, MessageKey.LOCATION_FIX_UNDERGROUND);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i == MaxHeight) {
|
||||||
|
TeleportUtils.teleport(player, JoinBlock.getLocation().add(0.5, 1.1, 0.5));
|
||||||
|
messages.send(player, MessageKey.LOCATION_FIX_UNDERGROUND_CANT_FIX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -139,7 +139,8 @@ public class OnJoinVerifier implements Reloadable {
|
|||||||
}
|
}
|
||||||
Player nonVipPlayer = generateKickPlayer(onlinePlayers);
|
Player nonVipPlayer = generateKickPlayer(onlinePlayers);
|
||||||
if (nonVipPlayer != null) {
|
if (nonVipPlayer != null) {
|
||||||
nonVipPlayer.kickPlayer(messages.retrieveSingle(player, MessageKey.KICK_FOR_VIP));
|
// AuthMeReReloaded - Folia compatibility
|
||||||
|
bukkitService.runTaskIfFolia(nonVipPlayer, () -> nonVipPlayer.kickPlayer(messages.retrieveSingle(player, MessageKey.KICK_FOR_VIP)));
|
||||||
event.allow();
|
event.allow();
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1,13 +1,5 @@
|
|||||||
package fr.xephi.authme.listener;
|
package fr.xephi.authme.listener;
|
||||||
|
|
||||||
import com.comphenix.protocol.PacketType;
|
|
||||||
import com.comphenix.protocol.ProtocolLibrary;
|
|
||||||
import com.comphenix.protocol.events.ListenerPriority;
|
|
||||||
import com.comphenix.protocol.events.PacketAdapter;
|
|
||||||
import fr.xephi.authme.AuthMe;
|
|
||||||
import fr.xephi.authme.listener.RegisterListener;
|
|
||||||
import com.comphenix.protocol.events.PacketEvent;
|
|
||||||
import fr.xephi.authme.api.v3.AuthMeApi;
|
|
||||||
import fr.xephi.authme.data.QuickCommandsProtectionManager;
|
import fr.xephi.authme.data.QuickCommandsProtectionManager;
|
||||||
import fr.xephi.authme.data.auth.PlayerAuth;
|
import fr.xephi.authme.data.auth.PlayerAuth;
|
||||||
import fr.xephi.authme.datasource.DataSource;
|
import fr.xephi.authme.datasource.DataSource;
|
||||||
@@ -24,14 +16,14 @@ import fr.xephi.authme.service.ValidationService;
|
|||||||
import fr.xephi.authme.settings.Settings;
|
import fr.xephi.authme.settings.Settings;
|
||||||
import fr.xephi.authme.settings.SpawnLoader;
|
import fr.xephi.authme.settings.SpawnLoader;
|
||||||
import fr.xephi.authme.settings.properties.HooksSettings;
|
import fr.xephi.authme.settings.properties.HooksSettings;
|
||||||
|
import fr.xephi.authme.settings.properties.PluginSettings;
|
||||||
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
||||||
import fr.xephi.authme.settings.properties.RestrictionSettings;
|
import fr.xephi.authme.settings.properties.RestrictionSettings;
|
||||||
import fr.xephi.authme.settings.properties.SecuritySettings;
|
|
||||||
import fr.xephi.authme.util.TeleportUtils;
|
import fr.xephi.authme.util.TeleportUtils;
|
||||||
import org.bukkit.Bukkit;
|
import fr.xephi.authme.util.message.I18NUtils;
|
||||||
|
import fr.xephi.authme.util.message.MiniMessageUtils;
|
||||||
import org.bukkit.ChatColor;
|
import org.bukkit.ChatColor;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.entity.HumanEntity;
|
import org.bukkit.entity.HumanEntity;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
@@ -39,7 +31,6 @@ import org.bukkit.event.EventPriority;
|
|||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.block.SignChangeEvent;
|
import org.bukkit.event.block.SignChangeEvent;
|
||||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||||
import org.bukkit.event.entity.EntityPickupItemEvent;
|
|
||||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||||
import org.bukkit.event.inventory.InventoryOpenEvent;
|
import org.bukkit.event.inventory.InventoryOpenEvent;
|
||||||
import org.bukkit.event.player.AsyncPlayerChatEvent;
|
import org.bukkit.event.player.AsyncPlayerChatEvent;
|
||||||
@@ -61,30 +52,20 @@ import org.bukkit.event.player.PlayerMoveEvent;
|
|||||||
import org.bukkit.event.player.PlayerQuitEvent;
|
import org.bukkit.event.player.PlayerQuitEvent;
|
||||||
import org.bukkit.event.player.PlayerRespawnEvent;
|
import org.bukkit.event.player.PlayerRespawnEvent;
|
||||||
import org.bukkit.event.player.PlayerShearEntityEvent;
|
import org.bukkit.event.player.PlayerShearEntityEvent;
|
||||||
import org.bukkit.event.player.PlayerSwapHandItemsEvent;
|
|
||||||
import org.bukkit.inventory.Inventory;
|
|
||||||
import org.bukkit.inventory.InventoryView;
|
import org.bukkit.inventory.InventoryView;
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
import org.bukkit.inventory.meta.ItemMeta;
|
|
||||||
import org.bukkit.plugin.Plugin;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import static fr.xephi.authme.settings.properties.RestrictionSettings.ALLOWED_MOVEMENT_RADIUS;
|
import static fr.xephi.authme.settings.properties.RestrictionSettings.ALLOWED_MOVEMENT_RADIUS;
|
||||||
import static fr.xephi.authme.settings.properties.RestrictionSettings.ALLOW_UNAUTHED_MOVEMENT;
|
import static fr.xephi.authme.settings.properties.RestrictionSettings.ALLOW_UNAUTHED_MOVEMENT;
|
||||||
|
import static org.bukkit.Bukkit.getServer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listener class for player events.
|
* Listener class for player events.
|
||||||
*/
|
*/
|
||||||
public class PlayerListener implements Listener{
|
public class PlayerListener implements Listener {
|
||||||
private final AuthMeApi authmeApi = AuthMeApi.getInstance();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private Settings settings;
|
private Settings settings;
|
||||||
@Inject
|
@Inject
|
||||||
@@ -114,7 +95,6 @@ public class PlayerListener implements Listener{
|
|||||||
@Inject
|
@Inject
|
||||||
private QuickCommandsProtectionManager quickCommandsProtectionManager;
|
private QuickCommandsProtectionManager quickCommandsProtectionManager;
|
||||||
|
|
||||||
|
|
||||||
// Lowest priority to apply fast protection checks
|
// Lowest priority to apply fast protection checks
|
||||||
@EventHandler(priority = EventPriority.LOWEST)
|
@EventHandler(priority = EventPriority.LOWEST)
|
||||||
public void onAsyncPlayerPreLoginEventLowest(AsyncPlayerPreLoginEvent event) {
|
public void onAsyncPlayerPreLoginEventLowest(AsyncPlayerPreLoginEvent event) {
|
||||||
@@ -134,8 +114,10 @@ public class PlayerListener implements Listener{
|
|||||||
if (validationService.isUnrestricted(name)) {
|
if (validationService.isUnrestricted(name)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (settings.getProperty(HooksSettings.HOOK_FLOODGATE_PLAYER) && org.geysermc.floodgate.api.FloodgateApi.getInstance().isFloodgateId(event.getUniqueId())){
|
if (settings.getProperty(HooksSettings.HOOK_FLOODGATE_PLAYER) && settings.getProperty(HooksSettings.IGNORE_BEDROCK_NAME_CHECK)) {
|
||||||
return;
|
if (getServer().getPluginManager().getPlugin("floodgate") != null) {
|
||||||
|
if (org.geysermc.floodgate.api.FloodgateApi.getInstance().isFloodgateId(event.getUniqueId())) return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Non-blocking checks
|
// Non-blocking checks
|
||||||
try {
|
try {
|
||||||
@@ -206,7 +188,6 @@ public class PlayerListener implements Listener{
|
|||||||
@EventHandler(priority = EventPriority.NORMAL)
|
@EventHandler(priority = EventPriority.NORMAL)
|
||||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||||
final Player player = event.getPlayer();
|
final Player player = event.getPlayer();
|
||||||
final AuthMeApi authmeApi = AuthMeApi.getInstance();
|
|
||||||
if (!PlayerListener19Spigot.isPlayerSpawnLocationEventCalled()) {
|
if (!PlayerListener19Spigot.isPlayerSpawnLocationEventCalled()) {
|
||||||
teleportationService.teleportOnJoin(player);
|
teleportationService.teleportOnJoin(player);
|
||||||
}
|
}
|
||||||
@@ -233,7 +214,7 @@ public class PlayerListener implements Listener{
|
|||||||
|
|
||||||
String customJoinMessage = settings.getProperty(RegistrationSettings.CUSTOM_JOIN_MESSAGE);
|
String customJoinMessage = settings.getProperty(RegistrationSettings.CUSTOM_JOIN_MESSAGE);
|
||||||
if (!customJoinMessage.isEmpty()) {
|
if (!customJoinMessage.isEmpty()) {
|
||||||
customJoinMessage = ChatColor.translateAlternateColorCodes('&', customJoinMessage);
|
customJoinMessage = ChatColor.translateAlternateColorCodes('&', MiniMessageUtils.parseMiniMessageToLegacy(customJoinMessage));
|
||||||
event.setJoinMessage(customJoinMessage
|
event.setJoinMessage(customJoinMessage
|
||||||
.replace("{PLAYERNAME}", player.getName())
|
.replace("{PLAYERNAME}", player.getName())
|
||||||
.replace("{DISPLAYNAME}", player.getDisplayName())
|
.replace("{DISPLAYNAME}", player.getDisplayName())
|
||||||
@@ -268,6 +249,11 @@ public class PlayerListener implements Listener{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove data from locale map when player quit
|
||||||
|
if (settings.getProperty(PluginSettings.I18N_MESSAGES)) {
|
||||||
|
I18NUtils.removeLocale(player.getUniqueId());
|
||||||
|
}
|
||||||
|
|
||||||
if (antiBotService.wasPlayerKicked(player.getName())) {
|
if (antiBotService.wasPlayerKicked(player.getName())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -333,7 +319,8 @@ public class PlayerListener implements Listener{
|
|||||||
final Player player = event.getPlayer();
|
final Player player = event.getPlayer();
|
||||||
if (!quickCommandsProtectionManager.isAllowed(player.getName())) {
|
if (!quickCommandsProtectionManager.isAllowed(player.getName())) {
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
player.kickPlayer(messages.retrieveSingle(player, MessageKey.QUICK_COMMAND_PROTECTION_KICK));
|
bukkitService.runTaskIfFolia(player, () -> player.kickPlayer(messages.retrieveSingle(player, MessageKey.QUICK_COMMAND_PROTECTION_KICK)));
|
||||||
|
// AuthMeReReloaded - Folia compatibility
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (listenerService.shouldCancelEvent(player)) {
|
if (listenerService.shouldCancelEvent(player)) {
|
||||||
@@ -387,17 +374,9 @@ public class PlayerListener implements Listener{
|
|||||||
Location spawn = spawnLoader.getSpawnLocation(player);
|
Location spawn = spawnLoader.getSpawnLocation(player);
|
||||||
if (spawn != null && spawn.getWorld() != null) {
|
if (spawn != null && spawn.getWorld() != null) {
|
||||||
if (!player.getWorld().equals(spawn.getWorld())) {
|
if (!player.getWorld().equals(spawn.getWorld())) {
|
||||||
if(AuthMe.SATEnabled) {
|
|
||||||
TeleportUtils.teleport(player,spawn);
|
TeleportUtils.teleport(player,spawn);
|
||||||
} else {
|
|
||||||
player.teleport(spawn);
|
|
||||||
}
|
|
||||||
} else if (spawn.distance(player.getLocation()) > settings.getProperty(ALLOWED_MOVEMENT_RADIUS)) {
|
} else if (spawn.distance(player.getLocation()) > settings.getProperty(ALLOWED_MOVEMENT_RADIUS)) {
|
||||||
if(AuthMe.SATEnabled) {
|
|
||||||
TeleportUtils.teleport(player,spawn);
|
TeleportUtils.teleport(player,spawn);
|
||||||
} else {
|
|
||||||
player.teleport(spawn);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -488,12 +467,12 @@ public class PlayerListener implements Listener{
|
|||||||
* Inventory interactions
|
* Inventory interactions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
// @EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||||
public void onPlayerPickupItem(EntityPickupItemEvent event) {
|
// public void onPlayerPickupItem(EntityPickupItemEvent event) {
|
||||||
if (listenerService.shouldCancelEvent(event)) {
|
// if (listenerService.shouldCancelEvent(event)) {
|
||||||
event.setCancelled(true);
|
// event.setCancelled(true);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||||
public void onPlayerDropItem(PlayerDropItemEvent event) {
|
public void onPlayerDropItem(PlayerDropItemEvent event) {
|
||||||
@@ -516,21 +495,33 @@ public class PlayerListener implements Listener{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
private boolean isInventoryWhitelisted(InventoryView inventory) {
|
private boolean isInventoryWhitelisted(InventoryView inventory) {
|
||||||
if (inventory == null) {
|
if (inventory == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Set<String> whitelist = settings.getProperty(RestrictionSettings.UNRESTRICTED_INVENTORIES);
|
Set<String> whitelist = settings.getProperty(RestrictionSettings.UNRESTRICTED_INVENTORIES);
|
||||||
|
if (whitelist.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
//append a string for String whitelist
|
//append a string for String whitelist
|
||||||
return whitelist.contains(ChatColor.stripColor(inventory.getTitle()).toLowerCase(Locale.ROOT));
|
String invName = ChatColor.stripColor(inventory.getTitle()).toLowerCase(Locale.ROOT);
|
||||||
|
if (settings.getProperty(RestrictionSettings.STRICT_UNRESTRICTED_INVENTORIES_CHECK)) {
|
||||||
|
return whitelist.contains(invName);
|
||||||
|
}
|
||||||
|
for (String wl : whitelist) {
|
||||||
|
if (invName.contains(wl)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||||
public void onPlayerInventoryOpen(InventoryOpenEvent event) {
|
public void onPlayerInventoryOpen(InventoryOpenEvent event) {
|
||||||
final HumanEntity player = event.getPlayer();
|
final HumanEntity player = event.getPlayer();
|
||||||
Player ply = (Player) event.getPlayer();
|
|
||||||
if (listenerService.shouldCancelEvent(player)
|
if (listenerService.shouldCancelEvent(player)
|
||||||
&& !isInventoryWhitelisted(event.getView()) && listenerService.shouldCancelInvEvent(ply)) {
|
&& !isInventoryWhitelisted(event.getView())) {
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -548,12 +539,4 @@ public class PlayerListener implements Listener{
|
|||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@EventHandler(priority = EventPriority.LOWEST)
|
|
||||||
public void onSwitchHand(PlayerSwapHandItemsEvent event) {
|
|
||||||
Player player = event.getPlayer();
|
|
||||||
if (!player.isSneaking() || !player.hasPermission("keybindings.use"))
|
|
||||||
return;
|
|
||||||
event.setCancelled(true);
|
|
||||||
Bukkit.dispatchCommand(event.getPlayer(), "help");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package fr.xephi.authme.listener;
|
||||||
|
|
||||||
|
import fr.xephi.authme.settings.Settings;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.EventPriority;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.entity.EntityPickupItemEvent;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
public class PlayerListenerHigherThan18 implements Listener {
|
||||||
|
@Inject
|
||||||
|
private ListenerService listenerService;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private Settings settings;
|
||||||
|
|
||||||
|
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||||
|
public void onPlayerPickupItem(EntityPickupItemEvent event) {
|
||||||
|
if (listenerService.shouldCancelEvent(event)) {
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
package fr.xephi.authme.listener;
|
|
||||||
//Prevent Ghost Players
|
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.event.EventHandler;
|
|
||||||
import org.bukkit.event.Listener;
|
|
||||||
import org.bukkit.event.player.PlayerQuitEvent;
|
|
||||||
import org.bukkit.plugin.Plugin;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
public class PlayerQuitListener implements Listener {
|
|
||||||
private final Plugin plugin;
|
|
||||||
public PlayerQuitListener(Plugin plugin) {
|
|
||||||
this.plugin = plugin;
|
|
||||||
}
|
|
||||||
@EventHandler
|
|
||||||
public void onPlayerQuit(PlayerQuitEvent event) {
|
|
||||||
Player player = event.getPlayer();
|
|
||||||
String LastAddr = Objects.requireNonNull(player.getAddress()).getAddress().getHostAddress();
|
|
||||||
Bukkit.getScheduler().runTaskLater(plugin, new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (player.isOnline()) {
|
|
||||||
player.kickPlayer("You have been disconnected.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, 20L); // 20 ticks = 1 second
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
package fr.xephi.authme.listener;
|
||||||
|
|
||||||
|
import fr.xephi.authme.AuthMe;
|
||||||
|
import fr.xephi.authme.api.v3.AuthMeApi;
|
||||||
|
import fr.xephi.authme.service.BukkitService;
|
||||||
|
import fr.xephi.authme.settings.Settings;
|
||||||
|
import fr.xephi.authme.settings.properties.SecuritySettings;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.player.PlayerQuitEvent;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class PurgeListener implements Listener {
|
||||||
|
private final AuthMeApi authmeApi = AuthMeApi.getInstance();
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private Settings settings;
|
||||||
|
@Inject
|
||||||
|
private BukkitService bukkitService;
|
||||||
|
@Inject
|
||||||
|
private AuthMe plugin;
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||||
|
Player player = event.getPlayer();
|
||||||
|
String name = player.getName();
|
||||||
|
UUID playerUUID = event.getPlayer().getUniqueId();
|
||||||
|
if (!authmeApi.isRegistered(name)) {
|
||||||
|
if (settings.getProperty(SecuritySettings.PURGE_DATA_ON_QUIT)) {
|
||||||
|
bukkitService.runTaskLater(() -> {
|
||||||
|
if (!player.isOnline()) {
|
||||||
|
deletePlayerData(playerUUID);
|
||||||
|
deletePlayerStats(playerUUID);
|
||||||
|
deleteAuthMePlayerData(playerUUID);
|
||||||
|
}
|
||||||
|
}, 100L);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deletePlayerData(UUID playerUUID) {
|
||||||
|
// 获取服务器的存储文件夹路径
|
||||||
|
File serverFolder = Bukkit.getServer().getWorldContainer();
|
||||||
|
String worldFolderName = settings.getProperty(SecuritySettings.DELETE_PLAYER_DATA_WORLD);
|
||||||
|
// 构建playerdata文件夹路径
|
||||||
|
File playerDataFolder = new File(serverFolder, File.separator + worldFolderName + File.separator + "playerdata");
|
||||||
|
|
||||||
|
// 构建玩家数据文件路径
|
||||||
|
File playerDataFile = new File(playerDataFolder, File.separator + playerUUID + ".dat");
|
||||||
|
File playerDataOldFile = new File(playerDataFolder, File.separator + playerUUID + ".dat_old");
|
||||||
|
|
||||||
|
// 删除玩家数据文件
|
||||||
|
if (playerDataFile.exists()) {
|
||||||
|
playerDataFile.delete();
|
||||||
|
}
|
||||||
|
if (playerDataOldFile.exists()) {
|
||||||
|
playerDataOldFile.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteAuthMePlayerData(UUID playerUUID) {
|
||||||
|
File pluginFolder = plugin.getDataFolder();
|
||||||
|
File path = new File(pluginFolder, File.separator + "playerdata" + File.separator + playerUUID);
|
||||||
|
File dataFile = new File(path, File.separator + "data.json");
|
||||||
|
if (dataFile.exists()) {
|
||||||
|
dataFile.delete();
|
||||||
|
path.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deletePlayerStats(UUID playerUUID) {
|
||||||
|
// 获取服务器的存储文件夹路径
|
||||||
|
File serverFolder = Bukkit.getServer().getWorldContainer();
|
||||||
|
String worldFolderName = settings.getProperty(SecuritySettings.DELETE_PLAYER_DATA_WORLD);
|
||||||
|
// 构建stats文件夹路径
|
||||||
|
File statsFolder = new File(serverFolder, File.separator + worldFolderName + File.separator + "stats");
|
||||||
|
// 构建玩家统计数据文件路径
|
||||||
|
File statsFile = new File(statsFolder, File.separator + playerUUID + ".json");
|
||||||
|
// 删除玩家统计数据文件
|
||||||
|
if (statsFile.exists()) {
|
||||||
|
statsFile.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,133 +0,0 @@
|
|||||||
package fr.xephi.authme.listener;
|
|
||||||
|
|
||||||
import com.comphenix.protocol.PacketType;
|
|
||||||
import com.comphenix.protocol.ProtocolLibrary;
|
|
||||||
import com.comphenix.protocol.events.ListenerPriority;
|
|
||||||
import com.comphenix.protocol.events.PacketAdapter;
|
|
||||||
import com.comphenix.protocol.events.PacketEvent;
|
|
||||||
import com.comphenix.protocol.events.PacketListener;
|
|
||||||
import fr.xephi.authme.AuthMe;
|
|
||||||
import fr.xephi.authme.api.v3.AuthMeApi;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.event.EventHandler;
|
|
||||||
import org.bukkit.event.EventPriority;
|
|
||||||
import org.bukkit.event.Listener;
|
|
||||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
|
||||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
|
||||||
import org.bukkit.event.inventory.InventoryOpenEvent;
|
|
||||||
import org.bukkit.event.player.PlayerJoinEvent;
|
|
||||||
import org.bukkit.event.player.PlayerQuitEvent;
|
|
||||||
import org.bukkit.inventory.Inventory;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
import org.bukkit.inventory.meta.ItemMeta;
|
|
||||||
import org.bukkit.plugin.Plugin;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Random;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
|
|
||||||
import static org.bukkit.Bukkit.getLogger;
|
|
||||||
|
|
||||||
public class RegisterListener implements Listener {
|
|
||||||
private final AuthMeApi authmeApi = AuthMeApi.getInstance();
|
|
||||||
private final Plugin plugin;
|
|
||||||
public static boolean enabled=true;
|
|
||||||
// 创建一个储存玩家关闭箱子GUI的原因的HashMap
|
|
||||||
public static HashMap<Player, String> closeReasonMap = new HashMap<>();
|
|
||||||
// Add a timer to kick the player if they don't verify in time
|
|
||||||
|
|
||||||
|
|
||||||
public RegisterListener(Plugin plugin) {
|
|
||||||
this.plugin = plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onInventoryClick(InventoryClickEvent event) {
|
|
||||||
if (event.getWhoClicked() instanceof Player) {
|
|
||||||
Player player = (Player) event.getWhoClicked();
|
|
||||||
ItemStack item = event.getCurrentItem();
|
|
||||||
// 获取点击事件的容器
|
|
||||||
Inventory inventory = event.getInventory();
|
|
||||||
if (event.getView().getTitle().equals("请验证你是真人")&&!authmeApi.isRegistered(player.getName())) {
|
|
||||||
if (Objects.requireNonNull(event.getCurrentItem()).getType().equals(Material.REDSTONE_BLOCK)) {
|
|
||||||
event.setCancelled(true);
|
|
||||||
closeReasonMap.put(player, "verified");
|
|
||||||
player.closeInventory();
|
|
||||||
player.sendMessage("§a验证完成");
|
|
||||||
//force to string
|
|
||||||
|
|
||||||
// ProtocolLibrary.getProtocolManager().removePacketListeners(this.plugin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler(ignoreCancelled = true,priority = EventPriority.HIGHEST)
|
|
||||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
|
||||||
Random random_blockpos = new Random();
|
|
||||||
int random_num = random_blockpos.nextInt(26);
|
|
||||||
Inventory menu = Bukkit.createInventory(null, 27, "请验证你是真人");
|
|
||||||
ItemStack item = new ItemStack(Material.REDSTONE_BLOCK);
|
|
||||||
ItemMeta meta = item.getItemMeta();
|
|
||||||
if (meta != null) {
|
|
||||||
meta.setDisplayName("§a我是真人");
|
|
||||||
}
|
|
||||||
item.setItemMeta(meta);
|
|
||||||
menu.setItem(random_num, item);
|
|
||||||
Player playerunreg = event.getPlayer();
|
|
||||||
String name = playerunreg.getName();
|
|
||||||
if (!authmeApi.isRegistered(name)) {
|
|
||||||
// getLogger().log(Level.INFO, "TESTTEST");
|
|
||||||
Bukkit.getScheduler().runTaskLater(this.plugin, () -> {
|
|
||||||
playerunreg.openInventory(menu);
|
|
||||||
}, 1L);
|
|
||||||
ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(this.plugin, ListenerPriority.HIGHEST, PacketType.Play.Client.CLOSE_WINDOW) {
|
|
||||||
@Override
|
|
||||||
public void onPacketReceiving(PacketEvent event) {
|
|
||||||
if (event.getPlayer() == playerunreg && !closeReasonMap.containsKey(playerunreg)) {
|
|
||||||
playerunreg.sendMessage("§c请先完成验证!");
|
|
||||||
event.setCancelled(true);
|
|
||||||
Bukkit.getScheduler().runTask(plugin, () -> {
|
|
||||||
playerunreg.openInventory(menu);
|
|
||||||
//playerunreg.kickPlayer("§c请先完成人机验证!");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(this.plugin, ListenerPriority.HIGHEST, PacketType.Play.Client.CHAT) {
|
|
||||||
@Override
|
|
||||||
public void onPacketReceiving(PacketEvent event) {
|
|
||||||
if (event.getPlayer() == playerunreg && !closeReasonMap.containsKey(playerunreg)) {
|
|
||||||
playerunreg.sendMessage("§c请先完成验证!");
|
|
||||||
event.setCancelled(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// chatListener = new PacketAdapter(this.plugin, ListenerPriority.HIGHEST, PacketType.Play.Client.CHAT) {
|
|
||||||
// @Override
|
|
||||||
// public void onPacketReceiving(PacketEvent event) {
|
|
||||||
// if (event.getPlayer() == player) {
|
|
||||||
// event.setCancelled(true);
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@EventHandler
|
|
||||||
public void onPlayerQuit(PlayerQuitEvent event){
|
|
||||||
Player player = event.getPlayer();
|
|
||||||
String name = player.getName();
|
|
||||||
if (!authmeApi.isRegistered(name)){closeReasonMap.remove(player);}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -53,6 +53,9 @@ public class ServerListener implements Listener {
|
|||||||
} else if ("ProtocolLib".equalsIgnoreCase(pluginName)) {
|
} else if ("ProtocolLib".equalsIgnoreCase(pluginName)) {
|
||||||
protocolLibService.disable();
|
protocolLibService.disable();
|
||||||
logger.warning("ProtocolLib has been disabled, unhooking packet adapters!");
|
logger.warning("ProtocolLib has been disabled, unhooking packet adapters!");
|
||||||
|
} else if ("PlaceholderAPI".equalsIgnoreCase(pluginName)) {
|
||||||
|
pluginHookService.unhookPlaceholderApi();
|
||||||
|
logger.info("PlaceholderAPI has been disabled: unhooking placeholders");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,6 +77,8 @@ public class ServerListener implements Listener {
|
|||||||
spawnLoader.loadCmiSpawn();
|
spawnLoader.loadCmiSpawn();
|
||||||
} else if ("ProtocolLib".equalsIgnoreCase(pluginName)) {
|
} else if ("ProtocolLib".equalsIgnoreCase(pluginName)) {
|
||||||
protocolLibService.setup();
|
protocolLibService.setup();
|
||||||
|
} else if ("PlaceholderAPI".equalsIgnoreCase(pluginName)) {
|
||||||
|
pluginHookService.tryHookToPlaceholderApi();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package fr.xephi.authme.listener.protocollib;
|
||||||
|
|
||||||
|
import com.comphenix.protocol.PacketType;
|
||||||
|
import com.comphenix.protocol.ProtocolLibrary;
|
||||||
|
import com.comphenix.protocol.events.ListenerPriority;
|
||||||
|
import com.comphenix.protocol.events.PacketAdapter;
|
||||||
|
import com.comphenix.protocol.events.PacketEvent;
|
||||||
|
import fr.xephi.authme.AuthMe;
|
||||||
|
import fr.xephi.authme.util.message.I18NUtils;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
class I18NGetLocalePacketAdapter extends PacketAdapter {
|
||||||
|
|
||||||
|
I18NGetLocalePacketAdapter(AuthMe plugin) {
|
||||||
|
super(plugin, ListenerPriority.NORMAL, PacketType.Play.Client.SETTINGS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPacketReceiving(PacketEvent event) {
|
||||||
|
if (event.getPacketType() == PacketType.Play.Client.SETTINGS) {
|
||||||
|
String locale = event.getPacket().getStrings().read(0).toLowerCase();
|
||||||
|
UUID uuid = event.getPlayer().getUniqueId();
|
||||||
|
|
||||||
|
I18NUtils.addLocale(uuid, locale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void register() {
|
||||||
|
ProtocolLibrary.getProtocolManager().addPacketListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unregister() {
|
||||||
|
ProtocolLibrary.getProtocolManager().removePacketListener(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -34,7 +34,6 @@ import org.bukkit.Material;
|
|||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,9 @@ import fr.xephi.authme.initialization.SettingsDependent;
|
|||||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||||
import fr.xephi.authme.service.BukkitService;
|
import fr.xephi.authme.service.BukkitService;
|
||||||
import fr.xephi.authme.settings.Settings;
|
import fr.xephi.authme.settings.Settings;
|
||||||
|
import fr.xephi.authme.settings.properties.PluginSettings;
|
||||||
import fr.xephi.authme.settings.properties.RestrictionSettings;
|
import fr.xephi.authme.settings.properties.RestrictionSettings;
|
||||||
|
import fr.xephi.authme.util.Utils;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
@@ -22,10 +24,12 @@ public class ProtocolLibService implements SettingsDependent {
|
|||||||
/* Packet Adapters */
|
/* Packet Adapters */
|
||||||
private InventoryPacketAdapter inventoryPacketAdapter;
|
private InventoryPacketAdapter inventoryPacketAdapter;
|
||||||
private TabCompletePacketAdapter tabCompletePacketAdapter;
|
private TabCompletePacketAdapter tabCompletePacketAdapter;
|
||||||
|
private I18NGetLocalePacketAdapter i18nGetLocalePacketAdapter;
|
||||||
|
|
||||||
/* Settings */
|
/* Settings */
|
||||||
private boolean protectInvBeforeLogin;
|
private boolean protectInvBeforeLogin;
|
||||||
private boolean denyTabCompleteBeforeLogin;
|
private boolean denyTabCompleteBeforeLogin;
|
||||||
|
private boolean i18nMessagesSending;
|
||||||
|
|
||||||
/* Service */
|
/* Service */
|
||||||
private boolean isEnabled;
|
private boolean isEnabled;
|
||||||
@@ -58,6 +62,10 @@ public class ProtocolLibService implements SettingsDependent {
|
|||||||
logger.warning("WARNING! The denyTabComplete feature requires ProtocolLib! Disabling it...");
|
logger.warning("WARNING! The denyTabComplete feature requires ProtocolLib! Disabling it...");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (i18nMessagesSending) {
|
||||||
|
logger.warning("WARNING! The i18n Messages feature requires ProtocolLib on lower version (< 1.15.2)! Disabling it...");
|
||||||
|
}
|
||||||
|
|
||||||
this.isEnabled = false;
|
this.isEnabled = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -84,6 +92,16 @@ public class ProtocolLibService implements SettingsDependent {
|
|||||||
tabCompletePacketAdapter = null;
|
tabCompletePacketAdapter = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (i18nMessagesSending) {
|
||||||
|
if (i18nGetLocalePacketAdapter == null) {
|
||||||
|
i18nGetLocalePacketAdapter = new I18NGetLocalePacketAdapter(plugin);
|
||||||
|
i18nGetLocalePacketAdapter.register();
|
||||||
|
}
|
||||||
|
} else if (i18nGetLocalePacketAdapter != null) {
|
||||||
|
i18nGetLocalePacketAdapter.unregister();
|
||||||
|
i18nGetLocalePacketAdapter = null;
|
||||||
|
}
|
||||||
|
|
||||||
this.isEnabled = true;
|
this.isEnabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,6 +119,10 @@ public class ProtocolLibService implements SettingsDependent {
|
|||||||
tabCompletePacketAdapter.unregister();
|
tabCompletePacketAdapter.unregister();
|
||||||
tabCompletePacketAdapter = null;
|
tabCompletePacketAdapter = null;
|
||||||
}
|
}
|
||||||
|
if (i18nGetLocalePacketAdapter != null) {
|
||||||
|
i18nGetLocalePacketAdapter.unregister();
|
||||||
|
i18nGetLocalePacketAdapter = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -120,6 +142,7 @@ public class ProtocolLibService implements SettingsDependent {
|
|||||||
|
|
||||||
this.protectInvBeforeLogin = settings.getProperty(RestrictionSettings.PROTECT_INVENTORY_BEFORE_LOGIN);
|
this.protectInvBeforeLogin = settings.getProperty(RestrictionSettings.PROTECT_INVENTORY_BEFORE_LOGIN);
|
||||||
this.denyTabCompleteBeforeLogin = settings.getProperty(RestrictionSettings.DENY_TABCOMPLETE_BEFORE_LOGIN);
|
this.denyTabCompleteBeforeLogin = settings.getProperty(RestrictionSettings.DENY_TABCOMPLETE_BEFORE_LOGIN);
|
||||||
|
this.i18nMessagesSending = settings.getProperty(PluginSettings.I18N_MESSAGES) && Utils.MAJOR_VERSION <= 15;
|
||||||
|
|
||||||
//it was true and will be deactivated now, so we need to restore the inventory for every player
|
//it was true and will be deactivated now, so we need to restore the inventory for every player
|
||||||
if (oldProtectInventory && !protectInvBeforeLogin && inventoryPacketAdapter != null) {
|
if (oldProtectInventory && !protectInvBeforeLogin && inventoryPacketAdapter != null) {
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ public class EmailService {
|
|||||||
try {
|
try {
|
||||||
htmlEmail = sendMailSsl.initializeMail(email);
|
htmlEmail = sendMailSsl.initializeMail(email);
|
||||||
} catch (EmailException e) {
|
} catch (EmailException e) {
|
||||||
logger.logException("Failed to create email for recovery code:", e);
|
logger.logException("Failed to create email for shutdown:", e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,12 +8,15 @@ import fr.xephi.authme.output.ConsoleLoggerFactory;
|
|||||||
import fr.xephi.authme.settings.Settings;
|
import fr.xephi.authme.settings.Settings;
|
||||||
import fr.xephi.authme.settings.properties.PluginSettings;
|
import fr.xephi.authme.settings.properties.PluginSettings;
|
||||||
import fr.xephi.authme.util.FileUtils;
|
import fr.xephi.authme.util.FileUtils;
|
||||||
|
import fr.xephi.authme.util.message.I18NUtils;
|
||||||
import org.bukkit.configuration.file.FileConfiguration;
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
import static fr.xephi.authme.message.MessagePathHelper.DEFAULT_LANGUAGE;
|
import static fr.xephi.authme.message.MessagePathHelper.DEFAULT_LANGUAGE;
|
||||||
|
|
||||||
@@ -33,6 +36,7 @@ public abstract class AbstractMessageFileHandler implements Reloadable {
|
|||||||
|
|
||||||
private String filename;
|
private String filename;
|
||||||
private FileConfiguration configuration;
|
private FileConfiguration configuration;
|
||||||
|
private Map<String, FileConfiguration> i18nConfiguration;
|
||||||
private final String defaultFile;
|
private final String defaultFile;
|
||||||
|
|
||||||
protected AbstractMessageFileHandler() {
|
protected AbstractMessageFileHandler() {
|
||||||
@@ -46,6 +50,7 @@ public abstract class AbstractMessageFileHandler implements Reloadable {
|
|||||||
filename = createFilePath(language);
|
filename = createFilePath(language);
|
||||||
File messagesFile = initializeFile(filename);
|
File messagesFile = initializeFile(filename);
|
||||||
configuration = YamlConfiguration.loadConfiguration(messagesFile);
|
configuration = YamlConfiguration.loadConfiguration(messagesFile);
|
||||||
|
i18nConfiguration = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String getLanguage() {
|
protected String getLanguage() {
|
||||||
@@ -83,6 +88,24 @@ public abstract class AbstractMessageFileHandler implements Reloadable {
|
|||||||
: message;
|
: message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the i18n message for the given key and given locale.
|
||||||
|
*
|
||||||
|
* @param key the key to retrieve the message for
|
||||||
|
* @param locale the locale that player client setting uses
|
||||||
|
* @return the message
|
||||||
|
*/
|
||||||
|
public String getMessageByLocale(String key, String locale) {
|
||||||
|
if (locale == null || !settings.getProperty(PluginSettings.I18N_MESSAGES)) {
|
||||||
|
return getMessage(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
String message = getI18nConfiguration(locale).getString(key);
|
||||||
|
return message == null
|
||||||
|
? "Error retrieving message '" + key + "'"
|
||||||
|
: message;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the message for the given key only if it exists,
|
* Returns the message for the given key only if it exists,
|
||||||
* i.e. without falling back to the default file.
|
* i.e. without falling back to the default file.
|
||||||
@@ -94,6 +117,27 @@ public abstract class AbstractMessageFileHandler implements Reloadable {
|
|||||||
return configuration.getString(key);
|
return configuration.getString(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public FileConfiguration getI18nConfiguration(String locale) {
|
||||||
|
if (i18nConfiguration == null) {
|
||||||
|
i18nConfiguration = new ConcurrentHashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
locale = I18NUtils.localeToCode(locale, settings);
|
||||||
|
|
||||||
|
if (i18nConfiguration.containsKey(locale)) {
|
||||||
|
return i18nConfiguration.get(locale);
|
||||||
|
} else {
|
||||||
|
// Sync with reload();
|
||||||
|
String i18nFilename = createFilePath(locale);
|
||||||
|
File i18nMessagesFile = initializeFile(i18nFilename);
|
||||||
|
FileConfiguration config = YamlConfiguration.loadConfiguration(i18nMessagesFile);
|
||||||
|
|
||||||
|
i18nConfiguration.put(locale, config);
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the path to the messages file for the given language code.
|
* Creates the path to the messages file for the given language code.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -4,14 +4,44 @@ package fr.xephi.authme.message;
|
|||||||
* Keys for translatable messages managed by {@link Messages}.
|
* Keys for translatable messages managed by {@link Messages}.
|
||||||
*/
|
*/
|
||||||
public enum MessageKey {
|
public enum MessageKey {
|
||||||
|
/**
|
||||||
|
* You have been disconnected due to doubled login.
|
||||||
|
*/
|
||||||
|
DOUBLE_LOGIN_FIX("double_login_fix.fix_message"),
|
||||||
|
|
||||||
/** In order to use this command you must be authenticated! */
|
/**
|
||||||
|
* You are stuck in portal during Login.
|
||||||
|
*/
|
||||||
|
LOCATION_FIX_PORTAL("login_location_fix.fix_portal"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* You are stuck underground during Login.
|
||||||
|
*/
|
||||||
|
LOCATION_FIX_UNDERGROUND("login_location_fix.fix_underground"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* You are stuck underground during Login, but we cant fix it.
|
||||||
|
*/
|
||||||
|
LOCATION_FIX_UNDERGROUND_CANT_FIX("login_location_fix.cannot_fix_underground"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bedrock auto login success!
|
||||||
|
*/
|
||||||
|
BEDROCK_AUTO_LOGGED_IN("bedrock_auto_login.success"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In order to use this command you must be authenticated!
|
||||||
|
*/
|
||||||
DENIED_COMMAND("error.denied_command"),
|
DENIED_COMMAND("error.denied_command"),
|
||||||
|
|
||||||
/** A player with the same IP is already in game! */
|
/**
|
||||||
|
* A player with the same IP is already in game!
|
||||||
|
*/
|
||||||
SAME_IP_ONLINE("on_join_validation.same_ip_online"),
|
SAME_IP_ONLINE("on_join_validation.same_ip_online"),
|
||||||
|
|
||||||
/** In order to chat you must be authenticated! */
|
/**
|
||||||
|
* In order to chat you must be authenticated!
|
||||||
|
*/
|
||||||
DENIED_CHAT("error.denied_chat"),
|
DENIED_CHAT("error.denied_chat"),
|
||||||
|
|
||||||
/** AntiBot protection mode is enabled! You have to wait some minutes before joining the server. */
|
/** AntiBot protection mode is enabled! You have to wait some minutes before joining the server. */
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import fr.xephi.authme.ConsoleLogger;
|
|||||||
import fr.xephi.authme.mail.EmailService;
|
import fr.xephi.authme.mail.EmailService;
|
||||||
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
import fr.xephi.authme.output.ConsoleLoggerFactory;
|
||||||
import fr.xephi.authme.util.expiring.Duration;
|
import fr.xephi.authme.util.expiring.Duration;
|
||||||
|
import fr.xephi.authme.util.message.I18NUtils;
|
||||||
|
import fr.xephi.authme.util.message.MiniMessageUtils;
|
||||||
import org.bukkit.ChatColor;
|
import org.bukkit.ChatColor;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
@@ -120,13 +122,16 @@ public class Messages {
|
|||||||
* @return The message from the file
|
* @return The message from the file
|
||||||
*/
|
*/
|
||||||
private String retrieveMessage(MessageKey key, CommandSender sender) {
|
private String retrieveMessage(MessageKey key, CommandSender sender) {
|
||||||
String message = messagesFileHandler.getMessage(key.getKey());
|
String locale = sender instanceof Player
|
||||||
|
? I18NUtils.getLocale((Player) sender)
|
||||||
|
: null;
|
||||||
|
String message = messagesFileHandler.getMessageByLocale(key.getKey(), locale);
|
||||||
String displayName = sender.getName();
|
String displayName = sender.getName();
|
||||||
if (sender instanceof Player) {
|
if (sender instanceof Player) {
|
||||||
displayName = ((Player) sender).getDisplayName();
|
displayName = ((Player) sender).getDisplayName();
|
||||||
}
|
}
|
||||||
|
|
||||||
return ChatColor.translateAlternateColorCodes('&', message)
|
return ChatColor.translateAlternateColorCodes('&', MiniMessageUtils.parseMiniMessageToLegacy(message))
|
||||||
.replace(NEWLINE_TAG, "\n")
|
.replace(NEWLINE_TAG, "\n")
|
||||||
.replace(USERNAME_TAG, sender.getName())
|
.replace(USERNAME_TAG, sender.getName())
|
||||||
.replace(DISPLAYNAME_TAG, displayName);
|
.replace(DISPLAYNAME_TAG, displayName);
|
||||||
@@ -142,7 +147,7 @@ public class Messages {
|
|||||||
private String retrieveMessage(MessageKey key, String name) {
|
private String retrieveMessage(MessageKey key, String name) {
|
||||||
String message = messagesFileHandler.getMessage(key.getKey());
|
String message = messagesFileHandler.getMessage(key.getKey());
|
||||||
|
|
||||||
return ChatColor.translateAlternateColorCodes('&', message)
|
return ChatColor.translateAlternateColorCodes('&', MiniMessageUtils.parseMiniMessageToLegacy(message))
|
||||||
.replace(NEWLINE_TAG, "\n")
|
.replace(NEWLINE_TAG, "\n")
|
||||||
.replace(USERNAME_TAG, name)
|
.replace(USERNAME_TAG, name)
|
||||||
.replace(DISPLAYNAME_TAG, name);
|
.replace(DISPLAYNAME_TAG, name);
|
||||||
|
|||||||
@@ -149,6 +149,9 @@ public class MessageUpdater {
|
|||||||
.put("verification", "Verification code")
|
.put("verification", "Verification code")
|
||||||
.put("time", "Time units")
|
.put("time", "Time units")
|
||||||
.put("two_factor", "Two-factor authentication")
|
.put("two_factor", "Two-factor authentication")
|
||||||
|
.put("bedrock_auto_login", "3rd party features: Bedrock Auto Login")
|
||||||
|
.put("login_location_fix", "3rd party features: Login Location Fix")
|
||||||
|
.put("double_login_fix", "3rd party features: Double Login Fix")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
Set<String> addedKeys = new HashSet<>();
|
Set<String> addedKeys = new HashSet<>();
|
||||||
@@ -167,7 +170,7 @@ public class MessageUpdater {
|
|||||||
|
|
||||||
// Create ConfigurationData instance
|
// Create ConfigurationData instance
|
||||||
Map<String, List<String>> commentsMap = comments.entrySet().stream()
|
Map<String, List<String>> commentsMap = comments.entrySet().stream()
|
||||||
.collect(Collectors.toMap(e -> e.getKey(), e -> singletonList(e.getValue())));
|
.collect(Collectors.toMap(Map.Entry::getKey, e -> singletonList(e.getValue())));
|
||||||
return new MessageKeyConfigurationData(builder, commentsMap);
|
return new MessageKeyConfigurationData(builder, commentsMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,4 +36,12 @@ public class MigraterYamlFileResource extends YamlFileResource {
|
|||||||
}
|
}
|
||||||
return singleQuoteYaml;
|
return singleQuoteYaml;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Because we set the YAML object to put strings in single quotes, this method by default uses that YAML object
|
||||||
|
// and also puts all paths as single quotes. Override to just always return the same string since we know those
|
||||||
|
// are only message names (so never any conflicting strings like "true" or "0").
|
||||||
|
@Override
|
||||||
|
protected String escapePathElementIfNeeded(String path) {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,9 @@ import fr.xephi.authme.service.SessionService;
|
|||||||
import fr.xephi.authme.service.ValidationService;
|
import fr.xephi.authme.service.ValidationService;
|
||||||
import fr.xephi.authme.service.bungeecord.BungeeSender;
|
import fr.xephi.authme.service.bungeecord.BungeeSender;
|
||||||
import fr.xephi.authme.service.bungeecord.MessageType;
|
import fr.xephi.authme.service.bungeecord.MessageType;
|
||||||
|
import fr.xephi.authme.service.velocity.VMessageType;
|
||||||
|
import fr.xephi.authme.service.velocity.VelocitySender;
|
||||||
|
import fr.xephi.authme.settings.Settings;
|
||||||
import fr.xephi.authme.settings.commandconfig.CommandManager;
|
import fr.xephi.authme.settings.commandconfig.CommandManager;
|
||||||
import fr.xephi.authme.settings.properties.HooksSettings;
|
import fr.xephi.authme.settings.properties.HooksSettings;
|
||||||
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
||||||
@@ -26,8 +29,6 @@ import fr.xephi.authme.util.PlayerUtils;
|
|||||||
import org.bukkit.GameMode;
|
import org.bukkit.GameMode;
|
||||||
import org.bukkit.Server;
|
import org.bukkit.Server;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.potion.PotionEffect;
|
|
||||||
import org.bukkit.potion.PotionEffectType;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
@@ -45,6 +46,9 @@ public class AsynchronousJoin implements AsynchronousProcess {
|
|||||||
@Inject
|
@Inject
|
||||||
private Server server;
|
private Server server;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private Settings settings;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private DataSource database;
|
private DataSource database;
|
||||||
|
|
||||||
@@ -75,6 +79,9 @@ public class AsynchronousJoin implements AsynchronousProcess {
|
|||||||
@Inject
|
@Inject
|
||||||
private BungeeSender bungeeSender;
|
private BungeeSender bungeeSender;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private VelocitySender velocitySender;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private ProxySessionManager proxySessionManager;
|
private ProxySessionManager proxySessionManager;
|
||||||
|
|
||||||
@@ -128,6 +135,10 @@ public class AsynchronousJoin implements AsynchronousProcess {
|
|||||||
|
|
||||||
// Session logic
|
// Session logic
|
||||||
if (sessionService.canResumeSession(player)) {
|
if (sessionService.canResumeSession(player)) {
|
||||||
|
if (velocitySender.isEnabled()) {
|
||||||
|
bukkitService.scheduleSyncDelayedTask(() ->
|
||||||
|
velocitySender.sendAuthMeVelocityMessage(player, VMessageType.LOGIN), service.getProperty(HooksSettings.PROXY_SEND_DELAY));
|
||||||
|
}
|
||||||
service.send(player, MessageKey.SESSION_RECONNECTION);
|
service.send(player, MessageKey.SESSION_RECONNECTION);
|
||||||
// Run commands
|
// Run commands
|
||||||
bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(
|
bukkitService.scheduleSyncTaskFromOptionallyAsyncTask(
|
||||||
@@ -152,7 +163,11 @@ public class AsynchronousJoin implements AsynchronousProcess {
|
|||||||
// As described at https://www.spigotmc.org/wiki/bukkit-bungee-plugin-messaging-channel/
|
// As described at https://www.spigotmc.org/wiki/bukkit-bungee-plugin-messaging-channel/
|
||||||
// "Keep in mind that you can't send plugin messages directly after a player joins."
|
// "Keep in mind that you can't send plugin messages directly after a player joins."
|
||||||
bukkitService.scheduleSyncDelayedTask(() ->
|
bukkitService.scheduleSyncDelayedTask(() ->
|
||||||
bungeeSender.sendAuthMeBungeecordMessage(player, MessageType.LOGIN), 5L);
|
bungeeSender.sendAuthMeBungeecordMessage(player, MessageType.LOGIN), settings.getProperty(HooksSettings.PROXY_SEND_DELAY));
|
||||||
|
}
|
||||||
|
if (velocitySender.isEnabled()) {
|
||||||
|
bukkitService.scheduleSyncDelayedTask(() ->
|
||||||
|
velocitySender.sendAuthMeVelocityMessage(player, VMessageType.LOGIN), settings.getProperty(HooksSettings.PROXY_SEND_DELAY));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -189,7 +204,9 @@ public class AsynchronousJoin implements AsynchronousProcess {
|
|||||||
if (service.getProperty(RegistrationSettings.APPLY_BLIND_EFFECT)) {
|
if (service.getProperty(RegistrationSettings.APPLY_BLIND_EFFECT)) {
|
||||||
// Allow infinite blindness effect
|
// Allow infinite blindness effect
|
||||||
int blindTimeOut = (registrationTimeout <= 0) ? 99999 : registrationTimeout;
|
int blindTimeOut = (registrationTimeout <= 0) ? 99999 : registrationTimeout;
|
||||||
player.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, blindTimeOut, 2));
|
|
||||||
|
// AuthMeReReloaded - Fix potion apply on Folia
|
||||||
|
bukkitService.runTaskIfFolia(player, () -> player.addPotionEffect(bukkitService.createBlindnessEffect(blindTimeOut)));
|
||||||
}
|
}
|
||||||
commandManager.runCommandsOnJoin(player);
|
commandManager.runCommandsOnJoin(player);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ import fr.xephi.authme.service.CommonService;
|
|||||||
import fr.xephi.authme.service.SessionService;
|
import fr.xephi.authme.service.SessionService;
|
||||||
import fr.xephi.authme.service.bungeecord.BungeeSender;
|
import fr.xephi.authme.service.bungeecord.BungeeSender;
|
||||||
import fr.xephi.authme.service.bungeecord.MessageType;
|
import fr.xephi.authme.service.bungeecord.MessageType;
|
||||||
|
import fr.xephi.authme.service.velocity.VelocitySender;
|
||||||
|
import fr.xephi.authme.settings.Settings;
|
||||||
import fr.xephi.authme.settings.properties.DatabaseSettings;
|
import fr.xephi.authme.settings.properties.DatabaseSettings;
|
||||||
import fr.xephi.authme.settings.properties.EmailSettings;
|
import fr.xephi.authme.settings.properties.EmailSettings;
|
||||||
import fr.xephi.authme.settings.properties.HooksSettings;
|
import fr.xephi.authme.settings.properties.HooksSettings;
|
||||||
@@ -81,9 +83,12 @@ public class AsynchronousLogin implements AsynchronousProcess {
|
|||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private SessionService sessionService;
|
private SessionService sessionService;
|
||||||
|
@Inject
|
||||||
|
private Settings settings;
|
||||||
@Inject
|
@Inject
|
||||||
private BungeeSender bungeeSender;
|
private BungeeSender bungeeSender;
|
||||||
|
@Inject
|
||||||
|
private VelocitySender velocitySender;
|
||||||
|
|
||||||
AsynchronousLogin() {
|
AsynchronousLogin() {
|
||||||
}
|
}
|
||||||
@@ -112,7 +117,7 @@ public class AsynchronousLogin implements AsynchronousProcess {
|
|||||||
*
|
*
|
||||||
* @param player the player to log in
|
* @param player the player to log in
|
||||||
*/
|
*/
|
||||||
public void forceLogin(Player player) {
|
public synchronized void forceLogin(Player player) {
|
||||||
PlayerAuth auth = getPlayerAuth(player);
|
PlayerAuth auth = getPlayerAuth(player);
|
||||||
if (auth != null) {
|
if (auth != null) {
|
||||||
performLogin(player, auth);
|
performLogin(player, auth);
|
||||||
@@ -306,7 +311,7 @@ public class AsynchronousLogin implements AsynchronousProcess {
|
|||||||
// As described at https://www.spigotmc.org/wiki/bukkit-bungee-plugin-messaging-channel/
|
// As described at https://www.spigotmc.org/wiki/bukkit-bungee-plugin-messaging-channel/
|
||||||
// "Keep in mind that you can't send plugin messages directly after a player joins."
|
// "Keep in mind that you can't send plugin messages directly after a player joins."
|
||||||
bukkitService.scheduleSyncDelayedTask(() ->
|
bukkitService.scheduleSyncDelayedTask(() ->
|
||||||
bungeeSender.sendAuthMeBungeecordMessage(player, MessageType.LOGIN), 5L);
|
bungeeSender.sendAuthMeBungeecordMessage(player, MessageType.LOGIN), settings.getProperty(HooksSettings.PROXY_SEND_DELAY));
|
||||||
}
|
}
|
||||||
|
|
||||||
// As the scheduling executes the Task most likely after the current
|
// As the scheduling executes the Task most likely after the current
|
||||||
|
|||||||
@@ -14,7 +14,10 @@ import fr.xephi.authme.service.CommonService;
|
|||||||
import fr.xephi.authme.service.JoinMessageService;
|
import fr.xephi.authme.service.JoinMessageService;
|
||||||
import fr.xephi.authme.service.TeleportationService;
|
import fr.xephi.authme.service.TeleportationService;
|
||||||
import fr.xephi.authme.service.bungeecord.BungeeSender;
|
import fr.xephi.authme.service.bungeecord.BungeeSender;
|
||||||
|
import fr.xephi.authme.service.velocity.VMessageType;
|
||||||
|
import fr.xephi.authme.service.velocity.VelocitySender;
|
||||||
import fr.xephi.authme.settings.commandconfig.CommandManager;
|
import fr.xephi.authme.settings.commandconfig.CommandManager;
|
||||||
|
import fr.xephi.authme.settings.properties.HooksSettings;
|
||||||
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.potion.PotionEffectType;
|
import org.bukkit.potion.PotionEffectType;
|
||||||
@@ -30,6 +33,9 @@ public class ProcessSyncPlayerLogin implements SynchronousProcess {
|
|||||||
@Inject
|
@Inject
|
||||||
private BungeeSender bungeeSender;
|
private BungeeSender bungeeSender;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private VelocitySender velocitySender;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private LimboService limboService;
|
private LimboService limboService;
|
||||||
|
|
||||||
@@ -86,6 +92,13 @@ public class ProcessSyncPlayerLogin implements SynchronousProcess {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final PlayerAuth auth = playerCache.getAuth(name);
|
final PlayerAuth auth = playerCache.getAuth(name);
|
||||||
|
|
||||||
|
// AuthMeReReloaded start - Fix #57
|
||||||
|
if (isFirstLogin) {
|
||||||
|
auth.setQuitLocation(player.getLocation());
|
||||||
|
}
|
||||||
|
// AuthMeReReloaded end - Fix #57
|
||||||
|
|
||||||
teleportationService.teleportOnLogin(player, auth, limbo);
|
teleportationService.teleportOnLogin(player, auth, limbo);
|
||||||
|
|
||||||
// We can now display the join message (if delayed)
|
// We can now display the join message (if delayed)
|
||||||
@@ -95,6 +108,13 @@ public class ProcessSyncPlayerLogin implements SynchronousProcess {
|
|||||||
player.removePotionEffect(PotionEffectType.BLINDNESS);
|
player.removePotionEffect(PotionEffectType.BLINDNESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AuthMeVelocity start - send on player login
|
||||||
|
if (velocitySender.isEnabled()) {
|
||||||
|
bukkitService.scheduleSyncDelayedTask(() ->
|
||||||
|
velocitySender.sendAuthMeVelocityMessage(player, VMessageType.LOGIN), commonService.getProperty(HooksSettings.PROXY_SEND_DELAY));
|
||||||
|
}
|
||||||
|
// AuthMeVelocity end
|
||||||
|
|
||||||
// The Login event now fires (as intended) after everything is processed
|
// The Login event now fires (as intended) after everything is processed
|
||||||
bukkitService.callEvent(new LoginEvent(player));
|
bukkitService.callEvent(new LoginEvent(player));
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ import fr.xephi.authme.service.CommonService;
|
|||||||
import fr.xephi.authme.service.SessionService;
|
import fr.xephi.authme.service.SessionService;
|
||||||
import fr.xephi.authme.service.bungeecord.BungeeSender;
|
import fr.xephi.authme.service.bungeecord.BungeeSender;
|
||||||
import fr.xephi.authme.service.bungeecord.MessageType;
|
import fr.xephi.authme.service.bungeecord.MessageType;
|
||||||
import fr.xephi.authme.settings.properties.RestrictionSettings;
|
import fr.xephi.authme.service.velocity.VMessageType;
|
||||||
|
import fr.xephi.authme.service.velocity.VelocitySender;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
@@ -42,6 +43,8 @@ public class AsynchronousLogout implements AsynchronousProcess {
|
|||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private BungeeSender bungeeSender;
|
private BungeeSender bungeeSender;
|
||||||
|
@Inject
|
||||||
|
private VelocitySender velocitySender;
|
||||||
|
|
||||||
AsynchronousLogout() {
|
AsynchronousLogout() {
|
||||||
}
|
}
|
||||||
@@ -61,17 +64,18 @@ public class AsynchronousLogout implements AsynchronousProcess {
|
|||||||
PlayerAuth auth = playerCache.getAuth(name);
|
PlayerAuth auth = playerCache.getAuth(name);
|
||||||
database.updateSession(auth);
|
database.updateSession(auth);
|
||||||
// TODO: send an update when a messaging service will be implemented (SESSION)
|
// TODO: send an update when a messaging service will be implemented (SESSION)
|
||||||
if (service.getProperty(RestrictionSettings.SAVE_QUIT_LOCATION)) {
|
//if (service.getProperty(RestrictionSettings.SAVE_QUIT_LOCATION)) {
|
||||||
auth.setQuitLocation(player.getLocation());
|
auth.setQuitLocation(player.getLocation());
|
||||||
database.updateQuitLoc(auth);
|
database.updateQuitLoc(auth);
|
||||||
// TODO: send an update when a messaging service will be implemented (QUITLOC)
|
// TODO: send an update when a messaging service will be implemented (QUITLOC)
|
||||||
}
|
//} AuthMeReReloaded - Always save quit location
|
||||||
|
|
||||||
playerCache.removePlayer(name);
|
playerCache.removePlayer(name);
|
||||||
codeManager.unverify(name);
|
codeManager.unverify(name);
|
||||||
database.setUnlogged(name);
|
database.setUnlogged(name);
|
||||||
sessionService.revokeSession(name);
|
sessionService.revokeSession(name);
|
||||||
bungeeSender.sendAuthMeBungeecordMessage(player, MessageType.LOGOUT);
|
bungeeSender.sendAuthMeBungeecordMessage(player, MessageType.LOGOUT);
|
||||||
|
velocitySender.sendAuthMeVelocityMessage(player, VMessageType.LOGOUT);
|
||||||
syncProcessManager.processSyncPlayerLogout(player);
|
syncProcessManager.processSyncPlayerLogout(player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,8 +14,6 @@ import fr.xephi.authme.settings.commandconfig.CommandManager;
|
|||||||
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
||||||
import fr.xephi.authme.settings.properties.RestrictionSettings;
|
import fr.xephi.authme.settings.properties.RestrictionSettings;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.potion.PotionEffect;
|
|
||||||
import org.bukkit.potion.PotionEffectType;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
@@ -75,7 +73,7 @@ public class ProcessSyncPlayerLogout implements SynchronousProcess {
|
|||||||
// Apply Blindness effect
|
// Apply Blindness effect
|
||||||
if (service.getProperty(RegistrationSettings.APPLY_BLIND_EFFECT)) {
|
if (service.getProperty(RegistrationSettings.APPLY_BLIND_EFFECT)) {
|
||||||
int timeout = service.getProperty(RestrictionSettings.TIMEOUT) * TICKS_PER_SECOND;
|
int timeout = service.getProperty(RestrictionSettings.TIMEOUT) * TICKS_PER_SECOND;
|
||||||
player.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, timeout, 2));
|
player.addPotionEffect(bukkitService.createBlindnessEffect(timeout));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set player's data to unauthenticated
|
// Set player's data to unauthenticated
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import fr.xephi.authme.service.SessionService;
|
|||||||
import fr.xephi.authme.service.ValidationService;
|
import fr.xephi.authme.service.ValidationService;
|
||||||
import fr.xephi.authme.settings.SpawnLoader;
|
import fr.xephi.authme.settings.SpawnLoader;
|
||||||
import fr.xephi.authme.settings.properties.PluginSettings;
|
import fr.xephi.authme.settings.properties.PluginSettings;
|
||||||
import fr.xephi.authme.settings.properties.RestrictionSettings;
|
|
||||||
import fr.xephi.authme.util.PlayerUtils;
|
import fr.xephi.authme.util.PlayerUtils;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
@@ -68,13 +67,16 @@ public class AsynchronousQuit implements AsynchronousProcess {
|
|||||||
boolean wasLoggedIn = playerCache.isAuthenticated(name);
|
boolean wasLoggedIn = playerCache.isAuthenticated(name);
|
||||||
|
|
||||||
if (wasLoggedIn) {
|
if (wasLoggedIn) {
|
||||||
if (service.getProperty(RestrictionSettings.SAVE_QUIT_LOCATION)) {
|
//if (service.getProperty(RestrictionSettings.SAVE_QUIT_LOCATION)) {
|
||||||
|
// AuthMeReReloaded - Always save quit location on quit
|
||||||
Location loc = spawnLoader.getPlayerLocationOrSpawn(player);
|
Location loc = spawnLoader.getPlayerLocationOrSpawn(player);
|
||||||
PlayerAuth auth = PlayerAuth.builder()
|
PlayerAuth authLoc = PlayerAuth.builder()
|
||||||
.name(name).location(loc)
|
.name(name).location(loc)
|
||||||
.realName(player.getName()).build();
|
.realName(player.getName()).build();
|
||||||
database.updateQuitLoc(auth);
|
database.updateQuitLoc(authLoc);
|
||||||
}
|
// AuthMeReReloaded - Fix AuthMe#2769 -1
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
String ip = PlayerUtils.getPlayerIp(player);
|
String ip = PlayerUtils.getPlayerIp(player);
|
||||||
PlayerAuth auth = PlayerAuth.builder()
|
PlayerAuth auth = PlayerAuth.builder()
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package fr.xephi.authme.process.quit;
|
package fr.xephi.authme.process.quit;
|
||||||
|
|
||||||
|
import com.github.Anon8281.universalScheduler.UniversalScheduler;
|
||||||
import fr.xephi.authme.data.limbo.LimboService;
|
import fr.xephi.authme.data.limbo.LimboService;
|
||||||
import fr.xephi.authme.process.SynchronousProcess;
|
import fr.xephi.authme.process.SynchronousProcess;
|
||||||
import fr.xephi.authme.settings.commandconfig.CommandManager;
|
import fr.xephi.authme.settings.commandconfig.CommandManager;
|
||||||
@@ -27,7 +28,9 @@ public class ProcessSyncPlayerQuit implements SynchronousProcess {
|
|||||||
commandManager.runCommandsOnLogout(player);
|
commandManager.runCommandsOnLogout(player);
|
||||||
} else {
|
} else {
|
||||||
limboService.restoreData(player);
|
limboService.restoreData(player);
|
||||||
player.saveData(); // #1238: Speed is sometimes not restored properly
|
if (!UniversalScheduler.isFolia) { // AuthMeReReloaded - Fix #146 (Very stupid solution, but works)
|
||||||
|
// player.saveData(); // #1238: Speed is sometimes not restored properly
|
||||||
|
}
|
||||||
}
|
}
|
||||||
player.leaveVehicle();
|
player.leaveVehicle();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ public class AsyncRegister implements AsynchronousProcess {
|
|||||||
* @param parameters the parameters
|
* @param parameters the parameters
|
||||||
* @param <P> parameters type
|
* @param <P> parameters type
|
||||||
*/
|
*/
|
||||||
public <P extends RegistrationParameters> void register(RegistrationMethod<P> variant, P parameters) {
|
public synchronized <P extends RegistrationParameters> void register(RegistrationMethod<P> variant, P parameters) {
|
||||||
if (preRegisterCheck(variant, parameters.getPlayer())) {
|
if (preRegisterCheck(variant, parameters.getPlayer())) {
|
||||||
RegistrationExecutor<P> executor = registrationExecutorFactory.getSingleton(variant.getExecutorClass());
|
RegistrationExecutor<P> executor = registrationExecutorFactory.getSingleton(variant.getExecutorClass());
|
||||||
if (executor.isRegistrationAdmitted(parameters)) {
|
if (executor.isRegistrationAdmitted(parameters)) {
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ import fr.xephi.authme.output.ConsoleLoggerFactory;
|
|||||||
import fr.xephi.authme.process.SynchronousProcess;
|
import fr.xephi.authme.process.SynchronousProcess;
|
||||||
import fr.xephi.authme.service.BukkitService;
|
import fr.xephi.authme.service.BukkitService;
|
||||||
import fr.xephi.authme.service.CommonService;
|
import fr.xephi.authme.service.CommonService;
|
||||||
|
import fr.xephi.authme.service.velocity.VMessageType;
|
||||||
|
import fr.xephi.authme.service.velocity.VelocitySender;
|
||||||
import fr.xephi.authme.util.PlayerUtils;
|
import fr.xephi.authme.util.PlayerUtils;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
@@ -28,6 +30,8 @@ public class ProcessSyncEmailRegister implements SynchronousProcess {
|
|||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private LimboService limboService;
|
private LimboService limboService;
|
||||||
|
@Inject
|
||||||
|
private VelocitySender velocitySender;
|
||||||
|
|
||||||
ProcessSyncEmailRegister() {
|
ProcessSyncEmailRegister() {
|
||||||
}
|
}
|
||||||
@@ -40,7 +44,7 @@ public class ProcessSyncEmailRegister implements SynchronousProcess {
|
|||||||
public void processEmailRegister(Player player) {
|
public void processEmailRegister(Player player) {
|
||||||
service.send(player, MessageKey.ACCOUNT_NOT_ACTIVATED);
|
service.send(player, MessageKey.ACCOUNT_NOT_ACTIVATED);
|
||||||
limboService.replaceTasksAfterRegistration(player);
|
limboService.replaceTasksAfterRegistration(player);
|
||||||
|
velocitySender.sendAuthMeVelocityMessage(player, VMessageType.REGISTER);
|
||||||
bukkitService.callEvent(new RegisterEvent(player));
|
bukkitService.callEvent(new RegisterEvent(player));
|
||||||
logger.fine(player.getName() + " registered " + PlayerUtils.getPlayerIp(player));
|
logger.fine(player.getName() + " registered " + PlayerUtils.getPlayerIp(player));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import fr.xephi.authme.process.SynchronousProcess;
|
|||||||
import fr.xephi.authme.service.BukkitService;
|
import fr.xephi.authme.service.BukkitService;
|
||||||
import fr.xephi.authme.service.CommonService;
|
import fr.xephi.authme.service.CommonService;
|
||||||
import fr.xephi.authme.service.bungeecord.BungeeSender;
|
import fr.xephi.authme.service.bungeecord.BungeeSender;
|
||||||
|
import fr.xephi.authme.service.velocity.VMessageType;
|
||||||
|
import fr.xephi.authme.service.velocity.VelocitySender;
|
||||||
import fr.xephi.authme.settings.commandconfig.CommandManager;
|
import fr.xephi.authme.settings.commandconfig.CommandManager;
|
||||||
import fr.xephi.authme.settings.properties.EmailSettings;
|
import fr.xephi.authme.settings.properties.EmailSettings;
|
||||||
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
||||||
@@ -27,6 +29,9 @@ public class ProcessSyncPasswordRegister implements SynchronousProcess {
|
|||||||
@Inject
|
@Inject
|
||||||
private BungeeSender bungeeSender;
|
private BungeeSender bungeeSender;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private VelocitySender velocitySender;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private CommonService service;
|
private CommonService service;
|
||||||
|
|
||||||
@@ -66,7 +71,7 @@ public class ProcessSyncPasswordRegister implements SynchronousProcess {
|
|||||||
if (!service.getProperty(EmailSettings.MAIL_ACCOUNT).isEmpty()) {
|
if (!service.getProperty(EmailSettings.MAIL_ACCOUNT).isEmpty()) {
|
||||||
service.send(player, MessageKey.ADD_EMAIL_MESSAGE);
|
service.send(player, MessageKey.ADD_EMAIL_MESSAGE);
|
||||||
}
|
}
|
||||||
|
velocitySender.sendAuthMeVelocityMessage(player, VMessageType.REGISTER);
|
||||||
bukkitService.callEvent(new RegisterEvent(player));
|
bukkitService.callEvent(new RegisterEvent(player));
|
||||||
logger.fine(player.getName() + " registered " + PlayerUtils.getPlayerIp(player));
|
logger.fine(player.getName() + " registered " + PlayerUtils.getPlayerIp(player));
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -10,7 +10,7 @@ import static fr.xephi.authme.process.register.executors.PlayerAuthBuilderHelper
|
|||||||
class PasswordRegisterExecutor extends AbstractPasswordRegisterExecutor<PasswordRegisterParams> {
|
class PasswordRegisterExecutor extends AbstractPasswordRegisterExecutor<PasswordRegisterParams> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PlayerAuth createPlayerAuthObject(PasswordRegisterParams params) {
|
public synchronized PlayerAuth createPlayerAuthObject(PasswordRegisterParams params) {
|
||||||
return createPlayerAuth(params.getPlayer(), params.getHashedPassword(), params.getEmail());
|
return createPlayerAuth(params.getPlayer(), params.getHashedPassword(), params.getEmail());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,13 +16,13 @@ import fr.xephi.authme.service.CommonService;
|
|||||||
import fr.xephi.authme.service.TeleportationService;
|
import fr.xephi.authme.service.TeleportationService;
|
||||||
import fr.xephi.authme.service.bungeecord.BungeeSender;
|
import fr.xephi.authme.service.bungeecord.BungeeSender;
|
||||||
import fr.xephi.authme.service.bungeecord.MessageType;
|
import fr.xephi.authme.service.bungeecord.MessageType;
|
||||||
|
import fr.xephi.authme.service.velocity.VMessageType;
|
||||||
|
import fr.xephi.authme.service.velocity.VelocitySender;
|
||||||
import fr.xephi.authme.settings.commandconfig.CommandManager;
|
import fr.xephi.authme.settings.commandconfig.CommandManager;
|
||||||
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
import fr.xephi.authme.settings.properties.RegistrationSettings;
|
||||||
import fr.xephi.authme.settings.properties.RestrictionSettings;
|
import fr.xephi.authme.settings.properties.RestrictionSettings;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.potion.PotionEffect;
|
|
||||||
import org.bukkit.potion.PotionEffectType;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
@@ -56,6 +56,9 @@ public class AsynchronousUnregister implements AsynchronousProcess {
|
|||||||
@Inject
|
@Inject
|
||||||
private CommandManager commandManager;
|
private CommandManager commandManager;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private VelocitySender velocitySender;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private BungeeSender bungeeSender;
|
private BungeeSender bungeeSender;
|
||||||
|
|
||||||
@@ -76,6 +79,7 @@ public class AsynchronousUnregister implements AsynchronousProcess {
|
|||||||
if (dataSource.removeAuth(name)) {
|
if (dataSource.removeAuth(name)) {
|
||||||
performPostUnregisterActions(name, player);
|
performPostUnregisterActions(name, player);
|
||||||
logger.info(name + " unregistered himself");
|
logger.info(name + " unregistered himself");
|
||||||
|
velocitySender.sendAuthMeVelocityMessage(player, VMessageType.UNREGISTER);
|
||||||
bukkitService.createAndCallEvent(isAsync -> new UnregisterByPlayerEvent(player, isAsync));
|
bukkitService.createAndCallEvent(isAsync -> new UnregisterByPlayerEvent(player, isAsync));
|
||||||
} else {
|
} else {
|
||||||
service.send(player, MessageKey.ERROR);
|
service.send(player, MessageKey.ERROR);
|
||||||
@@ -97,8 +101,8 @@ public class AsynchronousUnregister implements AsynchronousProcess {
|
|||||||
public void adminUnregister(CommandSender initiator, String name, Player player) {
|
public void adminUnregister(CommandSender initiator, String name, Player player) {
|
||||||
if (dataSource.removeAuth(name)) {
|
if (dataSource.removeAuth(name)) {
|
||||||
performPostUnregisterActions(name, player);
|
performPostUnregisterActions(name, player);
|
||||||
|
if (player != null) velocitySender.sendAuthMeVelocityMessage(player, VMessageType.FORCE_UNREGISTER);
|
||||||
bukkitService.createAndCallEvent(isAsync -> new UnregisterByAdminEvent(player, name, isAsync, initiator));
|
bukkitService.createAndCallEvent(isAsync -> new UnregisterByAdminEvent(player, name, isAsync, initiator));
|
||||||
|
|
||||||
if (initiator == null) {
|
if (initiator == null) {
|
||||||
logger.info(name + " was unregistered");
|
logger.info(name + " was unregistered");
|
||||||
} else {
|
} else {
|
||||||
@@ -144,7 +148,7 @@ public class AsynchronousUnregister implements AsynchronousProcess {
|
|||||||
private void applyBlindEffect(Player player) {
|
private void applyBlindEffect(Player player) {
|
||||||
if (service.getProperty(RegistrationSettings.APPLY_BLIND_EFFECT)) {
|
if (service.getProperty(RegistrationSettings.APPLY_BLIND_EFFECT)) {
|
||||||
int timeout = service.getProperty(RestrictionSettings.TIMEOUT) * TICKS_PER_SECOND;
|
int timeout = service.getProperty(RestrictionSettings.TIMEOUT) * TICKS_PER_SECOND;
|
||||||
player.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, timeout, 2));
|
bukkitService.runTaskIfFolia(player, () -> player.addPotionEffect(bukkitService.createBlindnessEffect(timeout)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user