Compare commits
379 Commits
Minecraft-
...
Minecraft-
Author | SHA1 | Date | |
---|---|---|---|
![]() |
a9603a6372 | ||
![]() |
b15ed87ad5 | ||
![]() |
3e816f628b | ||
![]() |
7bfc4bf819 | ||
![]() |
f8d15f4c88 | ||
![]() |
a73b06eee3 | ||
![]() |
2069679140 | ||
![]() |
9a173968f1 | ||
![]() |
13f1fa7443 | ||
![]() |
0f7da279ef | ||
![]() |
a6ba661a32 | ||
![]() |
22133bc8d2 | ||
![]() |
f9c9517958 | ||
![]() |
7a79bd0816 | ||
![]() |
6a60376033 | ||
![]() |
4ce0eee232 | ||
![]() |
72f3a79759 | ||
![]() |
dbb6aebf58 | ||
![]() |
54040ec48d | ||
![]() |
8c4ddf458c | ||
![]() |
07fb6490f8 | ||
![]() |
d9eb8c66b8 | ||
![]() |
7fab3ba372 | ||
![]() |
92c3ef1989 | ||
![]() |
fbf2d8969e | ||
![]() |
1881507712 | ||
![]() |
fd2a72477f | ||
![]() |
d4cbac1bdf | ||
![]() |
fa0671ab2a | ||
![]() |
184154a8b3 | ||
![]() |
cbec4e836a | ||
![]() |
3ce7982778 | ||
![]() |
b55944e2fb | ||
![]() |
12cba14657 | ||
![]() |
78e67283cc | ||
![]() |
f0f1e71c93 | ||
![]() |
3c1a5aabfd | ||
![]() |
f0d4e8c24a | ||
![]() |
ba8bd7faf0 | ||
![]() |
787692070e | ||
![]() |
523e991018 | ||
![]() |
7733fbfb28 | ||
![]() |
44ac36941f | ||
![]() |
0235c4a01e | ||
![]() |
b4220e9229 | ||
![]() |
9b9addfccd | ||
![]() |
b75a2b5060 | ||
![]() |
b5aecd5dcc | ||
![]() |
4d51d16512 | ||
![]() |
05a9342854 | ||
![]() |
483fede234 | ||
![]() |
ce8f1b44b6 | ||
![]() |
b1e3f6a75b | ||
![]() |
33d315b719 | ||
![]() |
d11e130d61 | ||
![]() |
45a93c8cfc | ||
![]() |
fd411edddb | ||
![]() |
ac5e8dbaff | ||
![]() |
340d82812a | ||
![]() |
eaf99cf4a6 | ||
![]() |
4baae5a230 | ||
![]() |
aa1a871967 | ||
![]() |
18f5ed3102 | ||
![]() |
d1dd7379b1 | ||
![]() |
0b0d09427d | ||
![]() |
dce0f6b408 | ||
![]() |
c5307c4451 | ||
![]() |
4f2b98188e | ||
![]() |
d5eb37c7a6 | ||
![]() |
2a421cdd8d | ||
![]() |
757f8f0cb9 | ||
![]() |
388d2620db | ||
![]() |
3ba52cb98b | ||
![]() |
e652214071 | ||
![]() |
0821404f92 | ||
![]() |
11b90b91b7 | ||
![]() |
aa3989db19 | ||
![]() |
76c914db14 | ||
![]() |
639e5f3c1d | ||
![]() |
9fd69068ae | ||
![]() |
9c35cad824 | ||
![]() |
d82b29e15a | ||
![]() |
9b0c827c37 | ||
![]() |
125d3f07f7 | ||
![]() |
2f45f0d578 | ||
![]() |
ad4c143ce4 | ||
![]() |
835e4e332c | ||
![]() |
0578f94522 | ||
![]() |
0cd4c9030c | ||
![]() |
0d666168f0 | ||
![]() |
cfb823f077 | ||
![]() |
36a5e89ff9 | ||
![]() |
bb4e8e29a5 | ||
![]() |
8e34e038d6 | ||
![]() |
d1950389cc | ||
![]() |
9d841bb91a | ||
![]() |
828cebcc4b | ||
![]() |
12fec2fcdd | ||
![]() |
8b6b134662 | ||
![]() |
538beb33a6 | ||
![]() |
97338cbfad | ||
![]() |
3e28decef2 | ||
![]() |
f93b647df3 | ||
![]() |
775ffdc998 | ||
![]() |
80c22027de | ||
![]() |
122987dd83 | ||
![]() |
ac4bab2425 | ||
![]() |
a51ffb1f4c | ||
![]() |
77e0dcc7f8 | ||
![]() |
ddb93fd988 | ||
![]() |
7eac22d362 | ||
![]() |
185dc97ca6 | ||
![]() |
e0d19cf305 | ||
![]() |
0e9002091b | ||
![]() |
9fdcded97f | ||
![]() |
32fdc83841 | ||
![]() |
1bf126d4f8 | ||
![]() |
56533c6259 | ||
![]() |
4cb46c6e5c | ||
![]() |
6decf860c9 | ||
![]() |
29f22f9be9 | ||
![]() |
98860ffd02 | ||
![]() |
2c225a05e7 | ||
![]() |
c1dfd0fb7b | ||
![]() |
9be44d51a6 | ||
![]() |
2a2c2717d5 | ||
![]() |
3f994a1c4c | ||
![]() |
9a0da50e6c | ||
![]() |
67fdc830c2 | ||
![]() |
64e8a79551 | ||
![]() |
afc387ce0d | ||
![]() |
8a70af5293 | ||
![]() |
57793e93f0 | ||
![]() |
a48ef137bd | ||
![]() |
ff32d29e09 | ||
![]() |
9f3359f8fa | ||
![]() |
539fccb873 | ||
![]() |
b25c81daf3 | ||
![]() |
21a354fa75 | ||
![]() |
aefe3333a9 | ||
![]() |
0afefa8f61 | ||
![]() |
834ac24b38 | ||
![]() |
c465eca03b | ||
![]() |
beb0bf9836 | ||
![]() |
688c42219c | ||
![]() |
1ea53f01aa | ||
![]() |
202dab5c98 | ||
![]() |
49ea7f908f | ||
![]() |
9d3bddedb6 | ||
![]() |
332bdaaec0 | ||
![]() |
904a1bfaa3 | ||
![]() |
5eb7a6eba7 | ||
![]() |
8e262cf428 | ||
![]() |
125df5c22d | ||
![]() |
7b631092f5 | ||
![]() |
d3c1339cc9 | ||
![]() |
679bf2fca9 | ||
![]() |
7436621481 | ||
![]() |
6236cff658 | ||
![]() |
6b504d9160 | ||
![]() |
d1124ca70b | ||
![]() |
779582d441 | ||
![]() |
b91564f77a | ||
![]() |
30b2e5008b | ||
![]() |
140830efe0 | ||
![]() |
5f8e76c61c | ||
![]() |
b7511abfda | ||
![]() |
09d04c34cb | ||
![]() |
3132d2c7cf | ||
![]() |
3682e8ba3a | ||
![]() |
82d5954f2f | ||
![]() |
384228b751 | ||
![]() |
50f8bd2eb0 | ||
![]() |
ff32764f9a | ||
![]() |
a1f928b210 | ||
![]() |
5bf616dc4d | ||
![]() |
0d7759f50b | ||
![]() |
824bdc5491 | ||
![]() |
ebff48ff86 | ||
![]() |
6efba44e5a | ||
![]() |
9f8ad518e8 | ||
![]() |
885a96c0c6 | ||
![]() |
5d0ff24f70 | ||
![]() |
ca5db43f70 | ||
![]() |
49a22f188f | ||
![]() |
ce7c095243 | ||
![]() |
cbb08ec58b | ||
![]() |
349949d154 | ||
![]() |
92e7faa346 | ||
![]() |
6b21fdaaea | ||
![]() |
fa9dd7e27f | ||
![]() |
f44cf6c8e9 | ||
![]() |
6bf9df31f5 | ||
![]() |
c08764990d | ||
![]() |
a82e6f3eea | ||
![]() |
26cee397e6 | ||
![]() |
dc6835c21b | ||
![]() |
be30c8b89a | ||
![]() |
70e10c382e | ||
![]() |
93ea108acb | ||
![]() |
a63739277b | ||
![]() |
112d543c2a | ||
![]() |
7338e20e98 | ||
![]() |
18a5534499 | ||
![]() |
e540626a28 | ||
![]() |
5e2bcc2907 | ||
![]() |
a38b3ce9f2 | ||
![]() |
c615b2362f | ||
![]() |
5620c4679d | ||
![]() |
a9ad4889f7 | ||
![]() |
7108bd4deb | ||
![]() |
ac1119bef8 | ||
![]() |
dac259933b | ||
![]() |
a57ae83d62 | ||
![]() |
a00c91c03a | ||
![]() |
a67d4a1697 | ||
![]() |
b87fff2614 | ||
![]() |
0c144c38db | ||
![]() |
5592f81e97 | ||
![]() |
5d1a2c59a7 | ||
![]() |
88c99f071e | ||
![]() |
19c3c23b86 | ||
![]() |
5dfe83cf6d | ||
![]() |
fecaf76acf | ||
![]() |
c8c1028bd9 | ||
![]() |
51be33dbd7 | ||
![]() |
8cac038a07 | ||
![]() |
edceaf072c | ||
![]() |
f935f93d98 | ||
![]() |
e5c457df04 | ||
![]() |
d4f60e65c3 | ||
![]() |
548b2f2c60 | ||
![]() |
3733ecf628 | ||
![]() |
6e9cdb2e20 | ||
![]() |
d900a5eae7 | ||
![]() |
68712ab854 | ||
![]() |
d067662967 | ||
![]() |
88a52bc4e9 | ||
![]() |
d684f5de69 | ||
![]() |
a316d6ccdc | ||
![]() |
5de8ac89e5 | ||
![]() |
8707995503 | ||
![]() |
caea1e3fa5 | ||
![]() |
4096012d8e | ||
![]() |
acbf6d3137 | ||
![]() |
3a3fb27d9a | ||
![]() |
e506957d38 | ||
![]() |
8003dc50c4 | ||
![]() |
75bc2738b9 | ||
![]() |
cf4846baa9 | ||
![]() |
120a4dc401 | ||
![]() |
6881597692 | ||
![]() |
0ffb557557 | ||
![]() |
5f7ecf9d3b | ||
![]() |
e07f1e603a | ||
![]() |
430b5ff392 | ||
![]() |
81fe547a7c | ||
![]() |
04fb1df3e1 | ||
![]() |
73aaf58009 | ||
![]() |
fd062503e1 | ||
![]() |
c97f113497 | ||
![]() |
14fcb90395 | ||
![]() |
39009d8c96 | ||
![]() |
13f394b9a7 | ||
![]() |
9838a09a8c | ||
![]() |
ffddcf939f | ||
![]() |
3d8143c36e | ||
![]() |
5e31b158e9 | ||
![]() |
a59e0f0b6b | ||
![]() |
517655f54e | ||
![]() |
55ec76beee | ||
![]() |
a564d4c7f1 | ||
![]() |
86b864ce21 | ||
![]() |
6813b82b84 | ||
![]() |
27d454524f | ||
![]() |
8827feacfb | ||
![]() |
692610cd7e | ||
![]() |
1edd27963f | ||
![]() |
730c05aaad | ||
![]() |
2bae6cafc2 | ||
![]() |
5a15d5387c | ||
![]() |
3fed94fbf2 | ||
![]() |
1dd661f619 | ||
![]() |
e364cff44e | ||
![]() |
dfa47f740d | ||
![]() |
87fcef0658 | ||
![]() |
49f2f5f28b | ||
![]() |
a12debf6d0 | ||
![]() |
5d3cb452fe | ||
![]() |
b3c34815b0 | ||
![]() |
40768c1711 | ||
![]() |
b16da7d048 | ||
![]() |
e681c8906d | ||
![]() |
ce40391717 | ||
![]() |
2e51ec4fba | ||
![]() |
54098c8989 | ||
![]() |
156ea30c32 | ||
![]() |
34f4bae923 | ||
![]() |
6bb089074e | ||
![]() |
70c73211a0 | ||
![]() |
c059345802 | ||
![]() |
f5b4e1242d | ||
![]() |
5365e5fb92 | ||
![]() |
dc2ef1eac7 | ||
![]() |
113dada511 | ||
![]() |
8ea5205fef | ||
![]() |
05d76c3f67 | ||
![]() |
d6e29b3f29 | ||
![]() |
bd479ba083 | ||
![]() |
704fe11b05 | ||
![]() |
4811e7be4f | ||
![]() |
ac426f0c3f | ||
![]() |
0f30024040 | ||
![]() |
5bfab582df | ||
![]() |
ec1de0f636 | ||
![]() |
9bf6a58ba2 | ||
![]() |
9483c0228b | ||
![]() |
09bb7a93d2 | ||
![]() |
8935e77118 | ||
![]() |
b71d253de2 | ||
![]() |
d54f2462a8 | ||
![]() |
c1ff4ffb89 | ||
![]() |
58f1ab208b | ||
![]() |
d5f25b07e5 | ||
![]() |
30b381853c | ||
![]() |
b0820208e6 | ||
![]() |
bc0a076e4b | ||
![]() |
1763dd3078 | ||
![]() |
373ec187fb | ||
![]() |
ac2c96c2ea | ||
![]() |
5688099605 | ||
![]() |
1d2afae98e | ||
![]() |
4805087e38 | ||
![]() |
e2f134ec08 | ||
![]() |
92c1450909 | ||
![]() |
fea3642550 | ||
![]() |
f02d17c979 | ||
![]() |
3dac86a94c | ||
![]() |
758e196479 | ||
![]() |
5dd3384b31 | ||
![]() |
59efec128d | ||
![]() |
3b90737273 | ||
![]() |
f9f664f9b6 | ||
![]() |
9edcda7ace | ||
![]() |
cd1420d9cd | ||
![]() |
a3e1493ce1 | ||
![]() |
9fb814003b | ||
![]() |
76319371f7 | ||
![]() |
2e33ab1460 | ||
![]() |
cfd10f5714 | ||
![]() |
6ae5feee60 | ||
![]() |
0b7b87d9c3 | ||
![]() |
fa5804ec86 | ||
![]() |
6e18403cd9 | ||
![]() |
f67ad024f5 | ||
![]() |
a0989a8932 | ||
![]() |
3be83cb5a4 | ||
![]() |
0ce02251d4 | ||
![]() |
b4d104d258 | ||
![]() |
0c69814db7 | ||
![]() |
f0766ebcfb | ||
![]() |
f0a19e0f45 | ||
![]() |
6525502836 | ||
![]() |
504f703fbb | ||
![]() |
4fb85721a9 | ||
![]() |
e12bc1d92e | ||
![]() |
bcaafc206f | ||
![]() |
8a96555cc7 | ||
![]() |
45c848a4fd | ||
![]() |
9e0ae0a70d | ||
![]() |
9ad9003974 | ||
![]() |
e18fe49cf9 | ||
![]() |
c3d702a5b3 | ||
![]() |
cdf26f7950 | ||
![]() |
644deee3c6 | ||
![]() |
b6e76f4054 | ||
![]() |
0f9cc76633 | ||
![]() |
0afc52c130 | ||
![]() |
0077af58d0 |
7
.gitignore
vendored
7
.gitignore
vendored
@@ -1,12 +1,11 @@
|
|||||||
# Eclipse stuff
|
# Eclipse stuff
|
||||||
.classpath/
|
.classpath
|
||||||
.project/
|
.project
|
||||||
.settings/
|
.settings
|
||||||
|
|
||||||
# netbeans
|
# netbeans
|
||||||
nbproject/
|
nbproject/
|
||||||
nbactions.xml
|
nbactions.xml
|
||||||
nb-configuration.xml
|
|
||||||
|
|
||||||
# we use maven!
|
# we use maven!
|
||||||
build.xml
|
build.xml
|
||||||
|
31
api/nb-configuration.xml
Normal file
31
api/nb-configuration.xml
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project-shared-configuration>
|
||||||
|
<!--
|
||||||
|
This file contains additional configuration written by modules in the NetBeans IDE.
|
||||||
|
The configuration is intended to be shared among all the users of project and
|
||||||
|
therefore it is assumed to be part of version control checkout.
|
||||||
|
Without this configuration present, some functionality in the IDE may be limited or fail altogether.
|
||||||
|
-->
|
||||||
|
<properties xmlns="http://www.netbeans.org/ns/maven-properties-data/1">
|
||||||
|
<!--
|
||||||
|
Properties that influence various parts of the IDE, especially code formatting and the like.
|
||||||
|
You can copy and paste the single properties, into the pom.xml file and the IDE will pick them up.
|
||||||
|
That way multiple projects can share the same settings (useful for formatting rules for example).
|
||||||
|
Any value defined here will override the pom.xml file value but is only applicable to the current project.
|
||||||
|
-->
|
||||||
|
<org-netbeans-modules-editor-indent.CodeStyle.usedProfile>project</org-netbeans-modules-editor-indent.CodeStyle.usedProfile>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.classDeclBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.classDeclBracePlacement>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.otherBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.otherBracePlacement>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.methodDeclBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.methodDeclBracePlacement>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinMethodCallParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinMethodCallParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSwitchParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSwitchParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinCatchParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinCatchParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinTryParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinTryParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSynchronizedParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSynchronizedParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinArrayInitBrackets>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinArrayInitBrackets>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinWhileParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinWhileParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinIfParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinIfParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinForParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinForParens>
|
||||||
|
</properties>
|
||||||
|
</project-shared-configuration>
|
26
api/pom.xml
26
api/pom.xml
@@ -6,13 +6,13 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>net.md-5</groupId>
|
<groupId>net.md-5</groupId>
|
||||||
<artifactId>bungeecord-parent</artifactId>
|
<artifactId>bungeecord-parent</artifactId>
|
||||||
<version>1.4.7-SNAPSHOT</version>
|
<version>1.5-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<groupId>net.md-5</groupId>
|
<groupId>net.md-5</groupId>
|
||||||
<artifactId>bungeecord-api</artifactId>
|
<artifactId>bungeecord-api</artifactId>
|
||||||
<version>1.4.7-SNAPSHOT</version>
|
<version>1.5-SNAPSHOT</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>BungeeCord-API</name>
|
<name>BungeeCord-API</name>
|
||||||
@@ -22,13 +22,31 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.google.guava</groupId>
|
<groupId>com.google.guava</groupId>
|
||||||
<artifactId>guava</artifactId>
|
<artifactId>guava</artifactId>
|
||||||
<version>13.0.1</version>
|
<version>14.0.1</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.ning</groupId>
|
||||||
|
<artifactId>async-http-client</artifactId>
|
||||||
|
<version>1.7.17</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.md-5</groupId>
|
||||||
|
<artifactId>bungeecord-event</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.md-5</groupId>
|
||||||
|
<artifactId>bungeecord-protocol</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.yaml</groupId>
|
<groupId>org.yaml</groupId>
|
||||||
<artifactId>snakeyaml</artifactId>
|
<artifactId>snakeyaml</artifactId>
|
||||||
<version>1.11</version>
|
<version>1.12</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
@@ -1,5 +1,7 @@
|
|||||||
package net.md_5.bungee.api;
|
package net.md_5.bungee.api;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -105,13 +107,30 @@ public enum ChatColor
|
|||||||
* Pattern to remove all colour codes.
|
* Pattern to remove all colour codes.
|
||||||
*/
|
*/
|
||||||
private static final Pattern STRIP_COLOR_PATTERN = Pattern.compile( "(?i)" + String.valueOf( COLOR_CHAR ) + "[0-9A-FK-OR]" );
|
private static final Pattern STRIP_COLOR_PATTERN = Pattern.compile( "(?i)" + String.valueOf( COLOR_CHAR ) + "[0-9A-FK-OR]" );
|
||||||
|
/**
|
||||||
|
* Colour instances keyed by their active character.
|
||||||
|
*/
|
||||||
|
private static final Map<Character, ChatColor> BY_CHAR = new HashMap<>();
|
||||||
|
/**
|
||||||
|
* The code appended to {@link #COLOR_CHAR} to make usable colour.
|
||||||
|
*/
|
||||||
|
private final char code;
|
||||||
/**
|
/**
|
||||||
* This colour's colour char prefixed by the {@link #COLOR_CHAR}.
|
* This colour's colour char prefixed by the {@link #COLOR_CHAR}.
|
||||||
*/
|
*/
|
||||||
private final String toString;
|
private final String toString;
|
||||||
|
|
||||||
|
static
|
||||||
|
{
|
||||||
|
for ( ChatColor colour : values() )
|
||||||
|
{
|
||||||
|
BY_CHAR.put( colour.code, colour );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private ChatColor(char code)
|
private ChatColor(char code)
|
||||||
{
|
{
|
||||||
|
this.code = code;
|
||||||
this.toString = new String( new char[]
|
this.toString = new String( new char[]
|
||||||
{
|
{
|
||||||
COLOR_CHAR, code
|
COLOR_CHAR, code
|
||||||
@@ -153,4 +172,15 @@ public enum ChatColor
|
|||||||
}
|
}
|
||||||
return new String( b );
|
return new String( b );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the colour represented by the specified code.
|
||||||
|
*
|
||||||
|
* @param code the code to search for
|
||||||
|
* @return the mapped colour, or null if non exists
|
||||||
|
*/
|
||||||
|
public static ChatColor getByChar(char code)
|
||||||
|
{
|
||||||
|
return BY_CHAR.get( code );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -19,6 +19,14 @@ public interface CommandSender
|
|||||||
*/
|
*/
|
||||||
public void sendMessage(String message);
|
public void sendMessage(String message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send several messages to this sender. Each message will be sent
|
||||||
|
* separately.
|
||||||
|
*
|
||||||
|
* @param messages the messages to send
|
||||||
|
*/
|
||||||
|
public void sendMessages(String... messages);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all groups this user is part of. This returns an unmodifiable
|
* Get all groups this user is part of. This returns an unmodifiable
|
||||||
* collection.
|
* collection.
|
||||||
|
@@ -2,6 +2,8 @@ package net.md_5.bungee.api;
|
|||||||
|
|
||||||
import net.md_5.bungee.api.plugin.PluginManager;
|
import net.md_5.bungee.api.plugin.PluginManager;
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
|
import com.ning.http.client.AsyncHttpClient;
|
||||||
|
import java.io.File;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -10,8 +12,9 @@ import lombok.Getter;
|
|||||||
import net.md_5.bungee.api.config.ConfigurationAdapter;
|
import net.md_5.bungee.api.config.ConfigurationAdapter;
|
||||||
import net.md_5.bungee.api.config.ServerInfo;
|
import net.md_5.bungee.api.config.ServerInfo;
|
||||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||||
import net.md_5.bungee.api.connection.Server;
|
|
||||||
import net.md_5.bungee.api.plugin.Plugin;
|
import net.md_5.bungee.api.plugin.Plugin;
|
||||||
|
import net.md_5.bungee.api.scheduler.TaskScheduler;
|
||||||
|
import net.md_5.bungee.api.tab.CustomTabList;
|
||||||
|
|
||||||
public abstract class ProxyServer
|
public abstract class ProxyServer
|
||||||
{
|
{
|
||||||
@@ -46,6 +49,13 @@ public abstract class ProxyServer
|
|||||||
*/
|
*/
|
||||||
public abstract String getVersion();
|
public abstract String getVersion();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a localized string from the .properties file.
|
||||||
|
*
|
||||||
|
* @return the localized string
|
||||||
|
*/
|
||||||
|
public abstract String getTranslation(String name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the main logger which can be used as a suitable replacement for
|
* Gets the main logger which can be used as a suitable replacement for
|
||||||
* {@link System#out} and {@link System#err}.
|
* {@link System#out} and {@link System#err}.
|
||||||
@@ -69,20 +79,6 @@ public abstract class ProxyServer
|
|||||||
*/
|
*/
|
||||||
public abstract ProxiedPlayer getPlayer(String name);
|
public abstract ProxiedPlayer getPlayer(String name);
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a server by its name. The instance returned will be taken from a
|
|
||||||
* player currently on that server to facilitate abstract proxy -> server
|
|
||||||
* actions.
|
|
||||||
*
|
|
||||||
* @param name the name to lookup
|
|
||||||
* @return the associated server
|
|
||||||
* @deprecated in most cases the {@link #getServerInfo(java.lang.String)}
|
|
||||||
* method should be used, as it will return a server even when no players
|
|
||||||
* are online.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public abstract Server getServer(String name);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return all servers registered to this proxy, keyed by name. Unlike the
|
* Return all servers registered to this proxy, keyed by name. Unlike the
|
||||||
* methods in {@link ConfigurationAdapter#getServers()}, this will not
|
* methods in {@link ConfigurationAdapter#getServers()}, this will not
|
||||||
@@ -124,21 +120,6 @@ public abstract class ProxyServer
|
|||||||
*/
|
*/
|
||||||
public abstract void setConfigurationAdapter(ConfigurationAdapter adapter);
|
public abstract void setConfigurationAdapter(ConfigurationAdapter adapter);
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the currently in use tab list handle.
|
|
||||||
*
|
|
||||||
* @return the tab list handler
|
|
||||||
*/
|
|
||||||
public abstract TabListHandler getTabListHandler();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the used tab list handler, should not be changed once players have
|
|
||||||
* connected
|
|
||||||
*
|
|
||||||
* @param handler the tab list handler to set
|
|
||||||
*/
|
|
||||||
public abstract void setTabListHandler(TabListHandler handler);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the currently in use reconnect handler.
|
* Get the currently in use reconnect handler.
|
||||||
*
|
*
|
||||||
@@ -208,7 +189,64 @@ public abstract class ProxyServer
|
|||||||
*
|
*
|
||||||
* @param name name of the server
|
* @param name name of the server
|
||||||
* @param address connectable Minecraft address + port of the server
|
* @param address connectable Minecraft address + port of the server
|
||||||
|
* @param restricted whether the server info restricted property will be set
|
||||||
* @return the constructed instance
|
* @return the constructed instance
|
||||||
*/
|
*/
|
||||||
public abstract ServerInfo constructServerInfo(String name, InetSocketAddress address);
|
public abstract ServerInfo constructServerInfo(String name, InetSocketAddress address, boolean restricted);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the console overlord for this proxy. Being the console, this
|
||||||
|
* command server cannot have permissions or groups, and will be able to
|
||||||
|
* execute anything.
|
||||||
|
*
|
||||||
|
* @return the console command sender of this proxy
|
||||||
|
*/
|
||||||
|
public abstract CommandSender getConsole();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the folder used to load plugins from.
|
||||||
|
*
|
||||||
|
* @return the folder used to load plugin
|
||||||
|
*/
|
||||||
|
public abstract File getPluginsFolder();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the scheduler instance for this proxy.
|
||||||
|
*
|
||||||
|
* @return the in use scheduler
|
||||||
|
*/
|
||||||
|
public abstract TaskScheduler getScheduler();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the the web client used by this proxy to facilitate making web
|
||||||
|
* requests. Care should be taken to ensure that all operations are non
|
||||||
|
* blocking where applicable.
|
||||||
|
*
|
||||||
|
* @return the server's {@link AsyncHttpClient} instance
|
||||||
|
*/
|
||||||
|
public abstract AsyncHttpClient getHttpClient();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current number of connected users. The default implementation is
|
||||||
|
* more efficient than {@link #getPlayers()} as it does not take a lock or
|
||||||
|
* make a copy.
|
||||||
|
*
|
||||||
|
* @return the current number of connected players
|
||||||
|
*/
|
||||||
|
public abstract int getOnlineCount();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send the specified message to the console and all connected players.
|
||||||
|
*
|
||||||
|
* @param message the message to broadcast
|
||||||
|
*/
|
||||||
|
public abstract void broadcast(String message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a new instance of this proxies custom tab list.
|
||||||
|
*
|
||||||
|
* @param player the player to generate this list in the context of
|
||||||
|
* @return a new {@link CustomTabList} instance
|
||||||
|
*/
|
||||||
|
public abstract CustomTabList customTabList(ProxiedPlayer player);
|
||||||
}
|
}
|
||||||
|
@@ -12,7 +12,7 @@ public interface ReconnectHandler
|
|||||||
* @param player the connecting player
|
* @param player the connecting player
|
||||||
* @return the server to connect to
|
* @return the server to connect to
|
||||||
*/
|
*/
|
||||||
public ServerInfo getServer(ProxiedPlayer player);
|
ServerInfo getServer(ProxiedPlayer player);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save the server of this player before they disconnect so it can be
|
* Save the server of this player before they disconnect so it can be
|
||||||
@@ -20,12 +20,20 @@ public interface ReconnectHandler
|
|||||||
*
|
*
|
||||||
* @param player the player to save
|
* @param player the player to save
|
||||||
*/
|
*/
|
||||||
public void setServer(ProxiedPlayer player);
|
void setServer(ProxiedPlayer player); // TOOD: String + String arguments?
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save all pending reconnect locations. Whilst not used for database
|
* Save all pending reconnect locations. Whilst not used for database
|
||||||
* connections, this method will be called at a predefined interval to allow
|
* connections, this method will be called at a predefined interval to allow
|
||||||
* the saving of reconnect files.
|
* the saving of reconnect files.
|
||||||
*/
|
*/
|
||||||
public void save();
|
void save();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close all connections indicating that the proxy is about to shutdown and
|
||||||
|
* all data should be saved. No new requests will be made after this method
|
||||||
|
* has been called.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void close();
|
||||||
}
|
}
|
||||||
|
@@ -3,6 +3,7 @@ package net.md_5.bungee.api.config;
|
|||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import net.md_5.bungee.api.tab.TabListHandler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class representing the configuration of a server listener. Used for allowing
|
* Class representing the configuration of a server listener. Used for allowing
|
||||||
@@ -32,6 +33,11 @@ public class ListenerInfo
|
|||||||
* Name of the server which users will be taken to by default.
|
* Name of the server which users will be taken to by default.
|
||||||
*/
|
*/
|
||||||
private final String defaultServer;
|
private final String defaultServer;
|
||||||
|
/**
|
||||||
|
* Name of the server which users will be taken when current server goes
|
||||||
|
* down.
|
||||||
|
*/
|
||||||
|
private final String fallbackServer;
|
||||||
/**
|
/**
|
||||||
* Whether reconnect locations will be used, or else the user is simply
|
* Whether reconnect locations will be used, or else the user is simply
|
||||||
* transferred to the default server on connect.
|
* transferred to the default server on connect.
|
||||||
@@ -42,4 +48,13 @@ public class ListenerInfo
|
|||||||
* transferred depending on the host they connect to.
|
* transferred depending on the host they connect to.
|
||||||
*/
|
*/
|
||||||
private final Map<String, String> forcedHosts;
|
private final Map<String, String> forcedHosts;
|
||||||
|
/**
|
||||||
|
* Get the texture pack used for servers connected to this proxy. May be
|
||||||
|
* null.
|
||||||
|
*/
|
||||||
|
private final TexturePackInfo texturePack;
|
||||||
|
/**
|
||||||
|
* Class used to build tab lists for this player.
|
||||||
|
*/
|
||||||
|
private final Class<? extends TabListHandler> tabList;
|
||||||
}
|
}
|
||||||
|
@@ -1,69 +1,49 @@
|
|||||||
package net.md_5.bungee.api.config;
|
package net.md_5.bungee.api.config;
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.Synchronized;
|
|
||||||
import net.md_5.bungee.api.Callback;
|
import net.md_5.bungee.api.Callback;
|
||||||
|
import net.md_5.bungee.api.CommandSender;
|
||||||
import net.md_5.bungee.api.ServerPing;
|
import net.md_5.bungee.api.ServerPing;
|
||||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class used to represent a server to connect to.
|
* Class used to represent a server to connect to.
|
||||||
*/
|
*/
|
||||||
@Data
|
public interface ServerInfo
|
||||||
@AllArgsConstructor
|
|
||||||
public abstract class ServerInfo
|
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Name this server displays as.
|
* Get the name of this server.
|
||||||
|
*
|
||||||
|
* @return the configured name for this server address
|
||||||
*/
|
*/
|
||||||
private final String name;
|
String getName();
|
||||||
/**
|
|
||||||
* Connectable address of this server.
|
|
||||||
*/
|
|
||||||
private final InetSocketAddress address;
|
|
||||||
/**
|
|
||||||
* Players connected to a server defined by these properties.
|
|
||||||
*/
|
|
||||||
private final Collection<ProxiedPlayer> players = new ArrayList<>();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a player to the internal set of this server.
|
* Gets the connectable host + port pair for this server. Implementations
|
||||||
|
* expect this to be used as the unique identifier per each instance of this
|
||||||
|
* class.
|
||||||
*
|
*
|
||||||
* @param player the player to add
|
* @return the IP and port pair for this server
|
||||||
*/
|
*/
|
||||||
@Synchronized("players")
|
InetSocketAddress getAddress();
|
||||||
public void addPlayer(ProxiedPlayer player)
|
|
||||||
{
|
|
||||||
players.add( player );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove a player form the internal set of this server.
|
|
||||||
*
|
|
||||||
* @param player the player to remove
|
|
||||||
*/
|
|
||||||
@Synchronized("players")
|
|
||||||
public void removePlayer(ProxiedPlayer player)
|
|
||||||
{
|
|
||||||
players.remove( player );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the set of all players on this server.
|
* Get the set of all players on this server.
|
||||||
*
|
*
|
||||||
* @return an unmodifiable collection of all players on this server
|
* @return an unmodifiable collection of all players on this server
|
||||||
*/
|
*/
|
||||||
@Synchronized("players")
|
Collection<ProxiedPlayer> getPlayers();
|
||||||
public Collection<ProxiedPlayer> getPlayers()
|
|
||||||
{
|
/**
|
||||||
return Collections.unmodifiableCollection( players );
|
* Whether the player can access this server. It will only return false when
|
||||||
}
|
* the player has no permission and this server is restricted.
|
||||||
|
*
|
||||||
|
* @param sender the player to check access for
|
||||||
|
* @return whether access is granted to this server
|
||||||
|
*/
|
||||||
|
boolean canAccess(CommandSender sender);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send data by any available means to this server.
|
* Send data by any available means to this server.
|
||||||
@@ -71,12 +51,12 @@ public abstract class ServerInfo
|
|||||||
* @param channel the channel to send this data via
|
* @param channel the channel to send this data via
|
||||||
* @param data the data to send
|
* @param data the data to send
|
||||||
*/
|
*/
|
||||||
public abstract void sendData(String channel, byte[] data);
|
void sendData(String channel, byte[] data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asynchronously gets the current player count on this server.
|
* Asynchronously gets the current player count on this server.
|
||||||
*
|
*
|
||||||
* @param callback the callback to call when the count has been retrieved.
|
* @param callback the callback to call when the count has been retrieved.
|
||||||
*/
|
*/
|
||||||
public abstract void ping(Callback<ServerPing> callback);
|
void ping(Callback<ServerPing> callback);
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,17 @@
|
|||||||
|
package net.md_5.bungee.api.config;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class TexturePackInfo
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The URL of the texture pack.
|
||||||
|
*/
|
||||||
|
private final String url;
|
||||||
|
/**
|
||||||
|
* The square dimension of this texture pack.
|
||||||
|
*/
|
||||||
|
private final int size;
|
||||||
|
}
|
@@ -1,6 +1,7 @@
|
|||||||
package net.md_5.bungee.api.connection;
|
package net.md_5.bungee.api.connection;
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
import net.md_5.bungee.protocol.packet.DefinedPacket;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A proxy connection is defined as a connection directly connected to a socket.
|
* A proxy connection is defined as a connection directly connected to a socket.
|
||||||
@@ -15,5 +16,33 @@ public interface Connection
|
|||||||
*
|
*
|
||||||
* @return the remote address
|
* @return the remote address
|
||||||
*/
|
*/
|
||||||
public InetSocketAddress getAddress();
|
InetSocketAddress getAddress();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disconnects this end of the connection for the specified reason. If this
|
||||||
|
* is an {@link ProxiedPlayer} the respective server connection will be
|
||||||
|
* closed too.
|
||||||
|
*
|
||||||
|
* @param reason the reason shown to the player / sent to the server on
|
||||||
|
* disconnect
|
||||||
|
*/
|
||||||
|
void disconnect(String reason);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the unsafe methods of this class.
|
||||||
|
*
|
||||||
|
* @return the unsafe method interface
|
||||||
|
*/
|
||||||
|
Unsafe unsafe();
|
||||||
|
|
||||||
|
interface Unsafe
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a packet to this connection.
|
||||||
|
*
|
||||||
|
* @param packet the packet to send
|
||||||
|
*/
|
||||||
|
void sendPacket(DefinedPacket packet);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -30,14 +30,6 @@ public interface PendingConnection extends Connection
|
|||||||
*/
|
*/
|
||||||
public InetSocketAddress getVirtualHost();
|
public InetSocketAddress getVirtualHost();
|
||||||
|
|
||||||
/**
|
|
||||||
* Completely kick this user from the proxy and all of its child
|
|
||||||
* connections.
|
|
||||||
*
|
|
||||||
* @param reason the disconnect reason displayed to the player
|
|
||||||
*/
|
|
||||||
public void disconnect(String reason);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the listener that accepted this connection.
|
* Get the listener that accepted this connection.
|
||||||
*
|
*
|
||||||
|
@@ -2,6 +2,8 @@ package net.md_5.bungee.api.connection;
|
|||||||
|
|
||||||
import net.md_5.bungee.api.CommandSender;
|
import net.md_5.bungee.api.CommandSender;
|
||||||
import net.md_5.bungee.api.config.ServerInfo;
|
import net.md_5.bungee.api.config.ServerInfo;
|
||||||
|
import net.md_5.bungee.api.config.TexturePackInfo;
|
||||||
|
import net.md_5.bungee.api.tab.TabListHandler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a player who's connection is being connected to somewhere else,
|
* Represents a player who's connection is being connected to somewhere else,
|
||||||
@@ -15,7 +17,7 @@ public interface ProxiedPlayer extends Connection, CommandSender
|
|||||||
*
|
*
|
||||||
* @return the players current display name
|
* @return the players current display name
|
||||||
*/
|
*/
|
||||||
public String getDisplayName();
|
String getDisplayName();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets this players display name to be used as their nametag and tab list
|
* Sets this players display name to be used as their nametag and tab list
|
||||||
@@ -23,7 +25,7 @@ public interface ProxiedPlayer extends Connection, CommandSender
|
|||||||
*
|
*
|
||||||
* @param name the name to set
|
* @param name the name to set
|
||||||
*/
|
*/
|
||||||
public void setDisplayName(String name);
|
void setDisplayName(String name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connects / transfers this user to the specified connection, gracefully
|
* Connects / transfers this user to the specified connection, gracefully
|
||||||
@@ -32,28 +34,21 @@ public interface ProxiedPlayer extends Connection, CommandSender
|
|||||||
*
|
*
|
||||||
* @param target the new server to connect to
|
* @param target the new server to connect to
|
||||||
*/
|
*/
|
||||||
public void connect(ServerInfo target);
|
void connect(ServerInfo target);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the server this player is connected to.
|
* Gets the server this player is connected to.
|
||||||
*
|
*
|
||||||
* @return the server this player is connected to
|
* @return the server this player is connected to
|
||||||
*/
|
*/
|
||||||
public Server getServer();
|
Server getServer();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the ping time between the proxy and this connection.
|
* Gets the ping time between the proxy and this connection.
|
||||||
*
|
*
|
||||||
* @return the current ping time
|
* @return the current ping time
|
||||||
*/
|
*/
|
||||||
public int getPing();
|
int getPing();
|
||||||
|
|
||||||
/**
|
|
||||||
* Disconnect (remove) this player from the proxy with the specified reason.
|
|
||||||
*
|
|
||||||
* @param reason the reason displayed to the player
|
|
||||||
*/
|
|
||||||
public void disconnect(String reason);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a plugin message to this player.
|
* Send a plugin message to this player.
|
||||||
@@ -61,12 +56,41 @@ public interface ProxiedPlayer extends Connection, CommandSender
|
|||||||
* @param channel the channel to send this data via
|
* @param channel the channel to send this data via
|
||||||
* @param data the data to send
|
* @param data the data to send
|
||||||
*/
|
*/
|
||||||
public void sendData(String channel, byte[] data);
|
void sendData(String channel, byte[] data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the pending connection that belongs to this player.
|
* Get the pending connection that belongs to this player.
|
||||||
*
|
*
|
||||||
* @return the pending connection that this player used
|
* @return the pending connection that this player used
|
||||||
*/
|
*/
|
||||||
public PendingConnection getPendingConnection();
|
PendingConnection getPendingConnection();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make this player chat (say something), to the server he is currently on.
|
||||||
|
*
|
||||||
|
* @param message the message to say
|
||||||
|
*/
|
||||||
|
void chat(String message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a request to change the players texture pack.
|
||||||
|
*
|
||||||
|
* @param pack the pack to request
|
||||||
|
*/
|
||||||
|
void setTexturePack(TexturePackInfo pack);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the new tab list for the user. At this stage it is not advisable to
|
||||||
|
* change after the user has logged in!
|
||||||
|
*
|
||||||
|
* @param list the new list
|
||||||
|
*/
|
||||||
|
void setTabList(TabListHandler list);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current tab list.
|
||||||
|
*
|
||||||
|
* @return the tab list in use by this user
|
||||||
|
*/
|
||||||
|
TabListHandler getTabList();
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,5 @@
|
|||||||
package net.md_5.bungee.api.connection;
|
package net.md_5.bungee.api.connection;
|
||||||
|
|
||||||
import net.md_5.bungee.api.Callback;
|
|
||||||
import net.md_5.bungee.api.ServerPing;
|
|
||||||
import net.md_5.bungee.api.config.ServerInfo;
|
import net.md_5.bungee.api.config.ServerInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -24,14 +22,4 @@ public interface Server extends Connection
|
|||||||
* @param data the data to send
|
* @param data the data to send
|
||||||
*/
|
*/
|
||||||
public abstract void sendData(String channel, byte[] data);
|
public abstract void sendData(String channel, byte[] data);
|
||||||
|
|
||||||
/**
|
|
||||||
* Asynchronously gets the current player count on this server.
|
|
||||||
*
|
|
||||||
* @param callback the callback to call when the count has been retrieved.
|
|
||||||
* @deprecated use the corresponding method in {@link ServerInfo} for
|
|
||||||
* clarity
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public abstract void ping(Callback<ServerPing> callback);
|
|
||||||
}
|
}
|
||||||
|
75
api/src/main/java/net/md_5/bungee/api/event/AsyncEvent.java
Normal file
75
api/src/main/java/net/md_5/bungee/api/event/AsyncEvent.java
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
package net.md_5.bungee.api.event;
|
||||||
|
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.ToString;
|
||||||
|
import net.md_5.bungee.api.Callback;
|
||||||
|
import net.md_5.bungee.api.plugin.Event;
|
||||||
|
import net.md_5.bungee.api.plugin.Plugin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an event which depends on the result of asynchronous operations.
|
||||||
|
*
|
||||||
|
* @param <T> Type of this event
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@ToString(callSuper = true)
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class AsyncEvent<T> extends Event
|
||||||
|
{
|
||||||
|
|
||||||
|
private final Callback<T> done;
|
||||||
|
private final Set<Plugin> intents = Collections.newSetFromMap( new ConcurrentHashMap<Plugin, Boolean>() );
|
||||||
|
private final AtomicBoolean fired = new AtomicBoolean();
|
||||||
|
private final AtomicInteger latch = new AtomicInteger();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public void postCall()
|
||||||
|
{
|
||||||
|
fired.set( true );
|
||||||
|
if ( latch.get() == 0 )
|
||||||
|
{
|
||||||
|
done.done( (T) this, null );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register an intent that this plugin will continue to perform work on a
|
||||||
|
* background task, and wishes to let the event proceed once the registered
|
||||||
|
* background task has completed.
|
||||||
|
*
|
||||||
|
* @param plugin the plugin registering this intent
|
||||||
|
*/
|
||||||
|
public void registerIntent(Plugin plugin)
|
||||||
|
{
|
||||||
|
Preconditions.checkState( !fired.get(), "Event %s has already been fired", this );
|
||||||
|
Preconditions.checkState( !intents.contains( plugin ), "Plugin %s already registered intent for event %s", plugin, this );
|
||||||
|
|
||||||
|
intents.add( plugin );
|
||||||
|
latch.incrementAndGet();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies this event that this plugin has done all its required processing
|
||||||
|
* and wishes to let the event proceed.
|
||||||
|
*
|
||||||
|
* @param plugin a plugin which has an intent registered for this event
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public void completeIntent(Plugin plugin)
|
||||||
|
{
|
||||||
|
Preconditions.checkState( intents.contains( plugin ), "Plugin %s has not registered intent for event %s", plugin, this );
|
||||||
|
intents.remove( plugin );
|
||||||
|
if ( latch.decrementAndGet() == 0 && fired.get() )
|
||||||
|
{
|
||||||
|
done.done( (T) this, null );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -30,4 +30,14 @@ public class ChatEvent extends TargetedEvent implements Cancellable
|
|||||||
super( sender, receiver );
|
super( sender, receiver );
|
||||||
this.message = message;
|
this.message = message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether this message is valid as a command
|
||||||
|
*
|
||||||
|
* @return if this message is a command
|
||||||
|
*/
|
||||||
|
public boolean isCommand()
|
||||||
|
{
|
||||||
|
return message.length() > 0 && message.charAt( 0 ) == '/';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,9 +3,9 @@ package net.md_5.bungee.api.event;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
|
import net.md_5.bungee.api.Callback;
|
||||||
import net.md_5.bungee.api.connection.PendingConnection;
|
import net.md_5.bungee.api.connection.PendingConnection;
|
||||||
import net.md_5.bungee.api.plugin.Cancellable;
|
import net.md_5.bungee.api.plugin.Cancellable;
|
||||||
import net.md_5.bungee.api.plugin.Event;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event called to represent a player logging in.
|
* Event called to represent a player logging in.
|
||||||
@@ -13,7 +13,7 @@ import net.md_5.bungee.api.plugin.Event;
|
|||||||
@Data
|
@Data
|
||||||
@ToString(callSuper = false)
|
@ToString(callSuper = false)
|
||||||
@EqualsAndHashCode(callSuper = false)
|
@EqualsAndHashCode(callSuper = false)
|
||||||
public class LoginEvent extends Event implements Cancellable
|
public class LoginEvent extends AsyncEvent<LoginEvent> implements Cancellable
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -28,4 +28,10 @@ public class LoginEvent extends Event implements Cancellable
|
|||||||
* Connection attempting to login.
|
* Connection attempting to login.
|
||||||
*/
|
*/
|
||||||
private final PendingConnection connection;
|
private final PendingConnection connection;
|
||||||
|
|
||||||
|
public LoginEvent(PendingConnection connection, Callback<LoginEvent> done)
|
||||||
|
{
|
||||||
|
super( done );
|
||||||
|
this.connection = connection;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,40 @@
|
|||||||
|
package net.md_5.bungee.api.event;
|
||||||
|
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.ToString;
|
||||||
|
import net.md_5.bungee.api.CommandSender;
|
||||||
|
import net.md_5.bungee.api.plugin.Event;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the permission of a CommandSender is checked.
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@ToString(callSuper = false)
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
public class PermissionCheckEvent extends Event
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The command sender being checked for a permission.
|
||||||
|
*/
|
||||||
|
private final CommandSender sender;
|
||||||
|
/**
|
||||||
|
* The permission to check.
|
||||||
|
*/
|
||||||
|
private final String permission;
|
||||||
|
/**
|
||||||
|
* The outcome of this permission check.
|
||||||
|
*/
|
||||||
|
@Getter(AccessLevel.NONE)
|
||||||
|
private boolean hasPermission;
|
||||||
|
|
||||||
|
public boolean hasPermission()
|
||||||
|
{
|
||||||
|
return hasPermission;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,23 @@
|
|||||||
|
package net.md_5.bungee.api.event;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.ToString;
|
||||||
|
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||||
|
import net.md_5.bungee.api.plugin.Event;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event called as soon as a connection has an {@link ProxiedPlayer} and is
|
||||||
|
* ready to be connected to a server.
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@ToString(callSuper = false)
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
public class PostLoginEvent extends Event
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The player involved with this event.
|
||||||
|
*/
|
||||||
|
private final ProxiedPlayer player;
|
||||||
|
}
|
@@ -1,18 +1,17 @@
|
|||||||
package net.md_5.bungee.api.event;
|
package net.md_5.bungee.api.event;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
import net.md_5.bungee.api.config.ServerInfo;
|
import net.md_5.bungee.api.config.ServerInfo;
|
||||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||||
|
import net.md_5.bungee.api.plugin.Cancellable;
|
||||||
import net.md_5.bungee.api.plugin.Event;
|
import net.md_5.bungee.api.plugin.Event;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@AllArgsConstructor
|
|
||||||
@ToString(callSuper = false)
|
@ToString(callSuper = false)
|
||||||
@EqualsAndHashCode(callSuper = false)
|
@EqualsAndHashCode(callSuper = false)
|
||||||
public class ServerConnectEvent extends Event
|
public class ServerConnectEvent extends Event implements Cancellable
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -23,4 +22,14 @@ public class ServerConnectEvent extends Event
|
|||||||
* Server the player will be connected to.
|
* Server the player will be connected to.
|
||||||
*/
|
*/
|
||||||
private ServerInfo target;
|
private ServerInfo target;
|
||||||
|
/**
|
||||||
|
* Cancelled state.
|
||||||
|
*/
|
||||||
|
private boolean cancelled;
|
||||||
|
|
||||||
|
public ServerConnectEvent(ProxiedPlayer player, ServerInfo target)
|
||||||
|
{
|
||||||
|
this.player = player;
|
||||||
|
this.target = target;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,43 @@
|
|||||||
|
package net.md_5.bungee.api.event;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.ToString;
|
||||||
|
import net.md_5.bungee.api.config.ServerInfo;
|
||||||
|
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||||
|
import net.md_5.bungee.api.plugin.Cancellable;
|
||||||
|
import net.md_5.bungee.api.plugin.Event;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a player getting kicked from a server.
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@ToString(callSuper = false)
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
public class ServerKickEvent extends Event implements Cancellable
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancelled status.
|
||||||
|
*/
|
||||||
|
private boolean cancelled;
|
||||||
|
/**
|
||||||
|
* Player being kicked.
|
||||||
|
*/
|
||||||
|
private final ProxiedPlayer player;
|
||||||
|
/**
|
||||||
|
* Kick reason.
|
||||||
|
*/
|
||||||
|
private String kickReason;
|
||||||
|
/**
|
||||||
|
* Server to send player to if this event is cancelled.
|
||||||
|
*/
|
||||||
|
private ServerInfo cancelServer;
|
||||||
|
|
||||||
|
public ServerKickEvent(ProxiedPlayer player, String kickReason, ServerInfo cancelServer)
|
||||||
|
{
|
||||||
|
this.player = player;
|
||||||
|
this.kickReason = kickReason;
|
||||||
|
this.cancelServer = cancelServer;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,22 @@
|
|||||||
|
package net.md_5.bungee.api.event;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.ToString;
|
||||||
|
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||||
|
import net.md_5.bungee.api.plugin.Event;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when a player has changed servers.
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@ToString(callSuper = false)
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
public class ServerSwitchEvent extends Event
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Player whom the server is for.
|
||||||
|
*/
|
||||||
|
private final ProxiedPlayer player;
|
||||||
|
}
|
@@ -5,4 +5,11 @@ package net.md_5.bungee.api.plugin;
|
|||||||
*/
|
*/
|
||||||
public abstract class Event
|
public abstract class Event
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method called after this event has been dispatched to all handlers.
|
||||||
|
*/
|
||||||
|
public void postCall()
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,10 @@
|
|||||||
package net.md_5.bungee.api.plugin;
|
package net.md_5.bungee.api.plugin;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.logging.Logger;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import net.md_5.bungee.api.ProxyServer;
|
||||||
import net.md_5.bungee.api.config.ConfigurationAdapter;
|
import net.md_5.bungee.api.config.ConfigurationAdapter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -12,6 +16,12 @@ public class Plugin
|
|||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private PluginDescription description;
|
private PluginDescription description;
|
||||||
|
@Getter
|
||||||
|
private ProxyServer proxy;
|
||||||
|
@Getter
|
||||||
|
private File file;
|
||||||
|
@Getter
|
||||||
|
private Logger logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the plugin has just been loaded. Most of the proxy will not
|
* Called when the plugin has just been loaded. Most of the proxy will not
|
||||||
@@ -36,13 +46,41 @@ public class Plugin
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the data folder where this plugin may store arbitrary data. It will
|
||||||
|
* be a child of {@link ProxyServer#getPluginsFolder()}.
|
||||||
|
*
|
||||||
|
* @return the data folder of this plugin
|
||||||
|
*/
|
||||||
|
public final File getDataFolder()
|
||||||
|
{
|
||||||
|
return new File( getProxy().getPluginsFolder(), getDescription().getName() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a resource from within this plugins jar or container. Care must be
|
||||||
|
* taken to close the returned stream.
|
||||||
|
*
|
||||||
|
* @param name the full path name of this resource
|
||||||
|
* @return the stream for getting this resource, or null if it does not
|
||||||
|
* exist
|
||||||
|
*/
|
||||||
|
public final InputStream getResourceAsStream(String name)
|
||||||
|
{
|
||||||
|
return getClass().getClassLoader().getResourceAsStream( name );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called by the loader to initialize the fields in this plugin.
|
* Called by the loader to initialize the fields in this plugin.
|
||||||
*
|
*
|
||||||
* @param description the description that describes this plugin
|
* @param description the description that describes this plugin
|
||||||
|
* @param jarfile this plugins jar or container
|
||||||
*/
|
*/
|
||||||
final void init(PluginDescription description)
|
final void init(ProxyServer proxy, PluginDescription description)
|
||||||
{
|
{
|
||||||
|
this.proxy = proxy;
|
||||||
this.description = description;
|
this.description = description;
|
||||||
|
this.file = description.getFile();
|
||||||
|
this.logger = new PluginLogger( this );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -45,6 +45,6 @@ public class PluginClassloader extends URLClassLoader
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new ClassNotFoundException(name);
|
throw new ClassNotFoundException( name );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,12 +1,17 @@
|
|||||||
package net.md_5.bungee.api.plugin;
|
package net.md_5.bungee.api.plugin;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* POJO representing the plugin.yml file.
|
* POJO representing the plugin.yml file.
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class PluginDescription
|
public class PluginDescription
|
||||||
{
|
{
|
||||||
@@ -27,8 +32,12 @@ public class PluginDescription
|
|||||||
* Plugin author.
|
* Plugin author.
|
||||||
*/
|
*/
|
||||||
private String author;
|
private String author;
|
||||||
|
/**
|
||||||
public PluginDescription()
|
* Plugin hard dependencies.
|
||||||
{
|
*/
|
||||||
}
|
private Set<String> depends = new HashSet<>();
|
||||||
|
/**
|
||||||
|
* File we were loaded from.
|
||||||
|
*/
|
||||||
|
private File file = null;
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,25 @@
|
|||||||
|
package net.md_5.bungee.api.plugin;
|
||||||
|
|
||||||
|
import java.util.logging.LogRecord;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
import net.md_5.bungee.api.ProxyServer;
|
||||||
|
|
||||||
|
public class PluginLogger extends Logger
|
||||||
|
{
|
||||||
|
|
||||||
|
private String pluginName;
|
||||||
|
|
||||||
|
protected PluginLogger(Plugin plugin)
|
||||||
|
{
|
||||||
|
super( plugin.getClass().getCanonicalName(), null );
|
||||||
|
pluginName = "[" + plugin.getDescription().getName() + "] ";
|
||||||
|
setParent( ProxyServer.getInstance().getLogger() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void log(LogRecord logRecord)
|
||||||
|
{
|
||||||
|
logRecord.setMessage( pluginName + logRecord.getMessage() );
|
||||||
|
super.log( logRecord );
|
||||||
|
}
|
||||||
|
}
|
@@ -1,45 +1,62 @@
|
|||||||
package net.md_5.bungee.api.plugin;
|
package net.md_5.bungee.api.plugin;
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import com.google.common.eventbus.EventBus;
|
|
||||||
import com.google.common.eventbus.Subscribe;
|
import com.google.common.eventbus.Subscribe;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLClassLoader;
|
import java.net.URLClassLoader;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Stack;
|
||||||
import java.util.jar.JarEntry;
|
import java.util.jar.JarEntry;
|
||||||
import java.util.jar.JarFile;
|
import java.util.jar.JarFile;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
import net.md_5.bungee.api.ChatColor;
|
import net.md_5.bungee.api.ChatColor;
|
||||||
import net.md_5.bungee.api.CommandSender;
|
import net.md_5.bungee.api.CommandSender;
|
||||||
import net.md_5.bungee.api.ProxyServer;
|
import net.md_5.bungee.api.ProxyServer;
|
||||||
|
import net.md_5.bungee.event.EventBus;
|
||||||
|
import net.md_5.bungee.event.EventHandler;
|
||||||
import org.yaml.snakeyaml.Yaml;
|
import org.yaml.snakeyaml.Yaml;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class to manage bridging between plugin duties and implementation duties, for
|
* Class to manage bridging between plugin duties and implementation duties, for
|
||||||
* example event handling and plugin management.
|
* example event handling and plugin management.
|
||||||
*/
|
*/
|
||||||
|
@RequiredArgsConstructor
|
||||||
public class PluginManager
|
public class PluginManager
|
||||||
{
|
{
|
||||||
|
|
||||||
private static final Pattern argsSplit = Pattern.compile( " " );
|
private static final Pattern argsSplit = Pattern.compile( " " );
|
||||||
/*========================================================================*/
|
/*========================================================================*/
|
||||||
|
private final ProxyServer proxy;
|
||||||
|
/*========================================================================*/
|
||||||
private final Yaml yaml = new Yaml();
|
private final Yaml yaml = new Yaml();
|
||||||
private final EventBus eventBus = new EventBus();
|
private final EventBus eventBus;
|
||||||
private final Map<String, Plugin> plugins = new HashMap<>();
|
private final Map<String, Plugin> plugins = new LinkedHashMap<>();
|
||||||
private final Map<String, Command> commandMap = new HashMap<>();
|
private final Map<String, Command> commandMap = new HashMap<>();
|
||||||
|
private Map<String, PluginDescription> toLoad = new HashMap<>();
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public PluginManager(ProxyServer proxy)
|
||||||
|
{
|
||||||
|
this.proxy = proxy;
|
||||||
|
eventBus = new EventBus( proxy.getLogger(), Subscribe.class, EventHandler.class );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a command so that it may be executed.
|
* Register a command so that it may be executed.
|
||||||
*
|
*
|
||||||
|
* @param plugin the plugin owning this command
|
||||||
* @param command the command to register
|
* @param command the command to register
|
||||||
*/
|
*/
|
||||||
public void registerCommand(Command command)
|
public void registerCommand(Plugin plugin, Command command)
|
||||||
{
|
{
|
||||||
commandMap.put( command.getName().toLowerCase(), command );
|
commandMap.put( command.getName().toLowerCase(), command );
|
||||||
for ( String alias : command.getAliases() )
|
for ( String alias : command.getAliases() )
|
||||||
@@ -78,7 +95,7 @@ public class PluginManager
|
|||||||
String permission = command.getPermission();
|
String permission = command.getPermission();
|
||||||
if ( permission != null && !permission.isEmpty() && !sender.hasPermission( permission ) )
|
if ( permission != null && !permission.isEmpty() && !sender.hasPermission( permission ) )
|
||||||
{
|
{
|
||||||
sender.sendMessage( ChatColor.RED + "You do not have permission to execute this command!" );
|
sender.sendMessage( proxy.getTranslation( "no_permission" ) );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,65 +132,114 @@ public class PluginManager
|
|||||||
return plugins.get( name );
|
return plugins.get( name );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public void loadAndEnablePlugins()
|
||||||
* Enable all plugins by calling the {@link Plugin#onEnable()} method.
|
|
||||||
*/
|
|
||||||
public void enablePlugins()
|
|
||||||
{
|
{
|
||||||
for ( Map.Entry<String, Plugin> entry : plugins.entrySet() )
|
Map<PluginDescription, Boolean> pluginStatuses = new HashMap<>();
|
||||||
|
for ( Map.Entry<String, PluginDescription> entry : toLoad.entrySet() )
|
||||||
|
{
|
||||||
|
PluginDescription plugin = entry.getValue();
|
||||||
|
if ( !enablePlugin( pluginStatuses, new Stack<PluginDescription>(), plugin ) )
|
||||||
|
{
|
||||||
|
ProxyServer.getInstance().getLogger().warning( "Failed to enable " + entry.getKey() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
toLoad.clear();
|
||||||
|
toLoad = null;
|
||||||
|
|
||||||
|
for ( Plugin plugin : plugins.values() )
|
||||||
{
|
{
|
||||||
Plugin plugin = entry.getValue();
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
plugin.onEnable();
|
plugin.onEnable();
|
||||||
ProxyServer.getInstance().getLogger().log( Level.INFO, "Enabled plugin {0} version {1} by {2}", new Object[]
|
ProxyServer.getInstance().getLogger().log( Level.INFO, "Enabled plugin {0} version {1} by {2}", new Object[]
|
||||||
{
|
{
|
||||||
entry.getKey(), plugin.getDescription().getVersion(), plugin.getDescription().getAuthor()
|
plugin.getDescription().getName(), plugin.getDescription().getVersion(), plugin.getDescription().getAuthor()
|
||||||
} );
|
} );
|
||||||
} catch ( Exception ex )
|
} catch ( Throwable t )
|
||||||
{
|
{
|
||||||
ProxyServer.getInstance().getLogger().log( Level.WARNING, "Exception encountered when loading plugin: " + entry.getKey(), ex );
|
ProxyServer.getInstance().getLogger().log( Level.WARNING, "Exception encountered when loading plugin: " + plugin.getDescription().getName(), t );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private boolean enablePlugin(Map<PluginDescription, Boolean> pluginStatuses, Stack<PluginDescription> dependStack, PluginDescription plugin)
|
||||||
* Load a plugin from the specified file. This file must be in jar format.
|
|
||||||
* This will not enable plugins, {@link #enablePlugins()} must be called.
|
|
||||||
*
|
|
||||||
* @param file the file to load from
|
|
||||||
* @throws Exception Any exceptions encountered when loading a plugin from
|
|
||||||
* this file.
|
|
||||||
*/
|
|
||||||
public void loadPlugin(File file) throws Exception
|
|
||||||
{
|
{
|
||||||
Preconditions.checkNotNull( file, "file" );
|
if ( pluginStatuses.containsKey( plugin ) )
|
||||||
Preconditions.checkArgument( file.isFile(), "Must load from file" );
|
{
|
||||||
|
return pluginStatuses.get( plugin );
|
||||||
|
}
|
||||||
|
|
||||||
try ( JarFile jar = new JarFile( file ) )
|
// success status
|
||||||
{
|
boolean status = true;
|
||||||
JarEntry pdf = jar.getJarEntry( "plugin.yml" );
|
|
||||||
Preconditions.checkNotNull( pdf, "Plugin must have a plugin.yml" );
|
|
||||||
|
|
||||||
try ( InputStream in = jar.getInputStream( pdf ) )
|
// try to load dependencies first
|
||||||
|
for ( String dependName : plugin.getDepends() )
|
||||||
|
{
|
||||||
|
PluginDescription depend = toLoad.get( dependName );
|
||||||
|
Boolean dependStatus = depend != null ? pluginStatuses.get( depend ) : Boolean.FALSE;
|
||||||
|
|
||||||
|
if ( dependStatus == null )
|
||||||
|
{
|
||||||
|
if ( dependStack.contains( depend ) )
|
||||||
|
{
|
||||||
|
StringBuilder dependencyGraph = new StringBuilder();
|
||||||
|
for ( PluginDescription element : dependStack )
|
||||||
|
{
|
||||||
|
dependencyGraph.append( element.getName() ).append( " -> " );
|
||||||
|
}
|
||||||
|
dependencyGraph.append( plugin.getName() ).append( " -> " ).append( dependName );
|
||||||
|
ProxyServer.getInstance().getLogger().log( Level.WARNING, "Circular dependency detected: " + dependencyGraph );
|
||||||
|
status = false;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
dependStack.push( plugin );
|
||||||
|
dependStatus = this.enablePlugin( pluginStatuses, dependStack, depend );
|
||||||
|
dependStack.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( dependStatus == Boolean.FALSE )
|
||||||
|
{
|
||||||
|
ProxyServer.getInstance().getLogger().log( Level.WARNING, "{0} (required by {1}) is unavailable", new Object[]
|
||||||
|
{
|
||||||
|
depend.getName(), plugin.getName()
|
||||||
|
} );
|
||||||
|
status = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !status )
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// do actual loading
|
||||||
|
if ( status )
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
PluginDescription desc = yaml.loadAs( in, PluginDescription.class );
|
|
||||||
URLClassLoader loader = new PluginClassloader( new URL[]
|
URLClassLoader loader = new PluginClassloader( new URL[]
|
||||||
{
|
{
|
||||||
file.toURI().toURL()
|
plugin.getFile().toURI().toURL()
|
||||||
} );
|
} );
|
||||||
Class<?> main = loader.loadClass( desc.getMain() );
|
Class<?> main = loader.loadClass( plugin.getMain() );
|
||||||
Plugin plugin = (Plugin) main.getDeclaredConstructor().newInstance();
|
Plugin clazz = (Plugin) main.getDeclaredConstructor().newInstance();
|
||||||
|
|
||||||
plugin.init( desc );
|
clazz.init( proxy, plugin );
|
||||||
plugins.put( desc.getName(), plugin );
|
plugins.put( plugin.getName(), clazz );
|
||||||
plugin.onLoad();
|
clazz.onLoad();
|
||||||
ProxyServer.getInstance().getLogger().log( Level.INFO, "Loaded plugin {0} version {1} by {2}", new Object[]
|
ProxyServer.getInstance().getLogger().log( Level.INFO, "Loaded plugin {0} version {1} by {2}", new Object[]
|
||||||
{
|
{
|
||||||
desc.getName(), desc.getVersion(), desc.getAuthor()
|
plugin.getName(), plugin.getVersion(), plugin.getAuthor()
|
||||||
} );
|
} );
|
||||||
|
} catch ( Throwable t )
|
||||||
|
{
|
||||||
|
proxy.getLogger().log( Level.WARNING, "Error enabling plugin " + plugin.getName(), t );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pluginStatuses.put( plugin, status );
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -181,7 +247,7 @@ public class PluginManager
|
|||||||
*
|
*
|
||||||
* @param folder the folder to search for plugins in
|
* @param folder the folder to search for plugins in
|
||||||
*/
|
*/
|
||||||
public void loadPlugins(File folder)
|
public void detectPlugins(File folder)
|
||||||
{
|
{
|
||||||
Preconditions.checkNotNull( folder, "folder" );
|
Preconditions.checkNotNull( folder, "folder" );
|
||||||
Preconditions.checkArgument( folder.isDirectory(), "Must load from a directory" );
|
Preconditions.checkArgument( folder.isDirectory(), "Must load from a directory" );
|
||||||
@@ -190,9 +256,17 @@ public class PluginManager
|
|||||||
{
|
{
|
||||||
if ( file.isFile() && file.getName().endsWith( ".jar" ) )
|
if ( file.isFile() && file.getName().endsWith( ".jar" ) )
|
||||||
{
|
{
|
||||||
try
|
try ( JarFile jar = new JarFile( file ) )
|
||||||
{
|
{
|
||||||
loadPlugin( file );
|
JarEntry pdf = jar.getJarEntry( "plugin.yml" );
|
||||||
|
Preconditions.checkNotNull( pdf, "Plugin must have a plugin.yml" );
|
||||||
|
|
||||||
|
try ( InputStream in = jar.getInputStream( pdf ) )
|
||||||
|
{
|
||||||
|
PluginDescription desc = yaml.loadAs( in, PluginDescription.class );
|
||||||
|
desc.setFile( file );
|
||||||
|
toLoad.put( desc.getName(), desc );
|
||||||
|
}
|
||||||
} catch ( Exception ex )
|
} catch ( Exception ex )
|
||||||
{
|
{
|
||||||
ProxyServer.getInstance().getLogger().log( Level.WARNING, "Could not load plugin from file " + file, ex );
|
ProxyServer.getInstance().getLogger().log( Level.WARNING, "Could not load plugin from file " + file, ex );
|
||||||
@@ -211,7 +285,20 @@ public class PluginManager
|
|||||||
*/
|
*/
|
||||||
public <T extends Event> T callEvent(T event)
|
public <T extends Event> T callEvent(T event)
|
||||||
{
|
{
|
||||||
|
Preconditions.checkNotNull( event, "event" );
|
||||||
|
|
||||||
|
long start = System.nanoTime();
|
||||||
eventBus.post( event );
|
eventBus.post( event );
|
||||||
|
event.postCall();
|
||||||
|
|
||||||
|
long elapsed = start - System.nanoTime();
|
||||||
|
if ( elapsed > 250000 )
|
||||||
|
{
|
||||||
|
ProxyServer.getInstance().getLogger().log( Level.WARNING, "Event {0} took more {1}ns to process!", new Object[]
|
||||||
|
{
|
||||||
|
event, elapsed
|
||||||
|
} );
|
||||||
|
}
|
||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,10 +307,21 @@ public class PluginManager
|
|||||||
* Object which wish to receive events must be annotated with the
|
* Object which wish to receive events must be annotated with the
|
||||||
* {@link Subscribe} annotation.
|
* {@link Subscribe} annotation.
|
||||||
*
|
*
|
||||||
|
* @param plugin the owning plugin
|
||||||
* @param listener the listener to register events for
|
* @param listener the listener to register events for
|
||||||
*/
|
*/
|
||||||
public void registerListener(Listener listener)
|
public void registerListener(Plugin plugin, Listener listener)
|
||||||
{
|
{
|
||||||
|
for ( Method method : listener.getClass().getDeclaredMethods() )
|
||||||
|
{
|
||||||
|
if ( method.isAnnotationPresent( Subscribe.class ) )
|
||||||
|
{
|
||||||
|
proxy.getLogger().log( Level.WARNING, "Listener " + listener + " has registered using depreceated subscribe annotation!"
|
||||||
|
+ " Please advice author to update to @EventHandler."
|
||||||
|
+ " As a server owner you may safely ignore this.", new Exception() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
eventBus.register( listener );
|
eventBus.register( listener );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,41 @@
|
|||||||
|
package net.md_5.bungee.api.scheduler;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import net.md_5.bungee.api.plugin.Plugin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a task scheduled for execution by the {@link TaskScheduler}.
|
||||||
|
*/
|
||||||
|
public interface ScheduledTask
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the unique ID of this task.
|
||||||
|
*
|
||||||
|
* @return this tasks ID
|
||||||
|
*/
|
||||||
|
int getId();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the plugin which scheduled this task for execution.
|
||||||
|
*
|
||||||
|
* @return the owning plugin
|
||||||
|
*/
|
||||||
|
Plugin getOwner();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the actual method which will be executed by this task.
|
||||||
|
*
|
||||||
|
* @return the {@link Runnable} behind this task
|
||||||
|
*/
|
||||||
|
Runnable getTask();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the delay in the specified unit before this task will next be
|
||||||
|
* executed.
|
||||||
|
*
|
||||||
|
* @param unit the unit to get the delay in
|
||||||
|
* @return the time before the next execution of this task
|
||||||
|
*/
|
||||||
|
long getDelay(TimeUnit unit);
|
||||||
|
}
|
@@ -0,0 +1,74 @@
|
|||||||
|
package net.md_5.bungee.api.scheduler;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import net.md_5.bungee.api.plugin.Plugin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This interface represents a scheduler which may be used to queue, delay and
|
||||||
|
* execute tasks in an asynchronous fashion.
|
||||||
|
*/
|
||||||
|
public interface TaskScheduler
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancel a task to prevent it from executing, or if its a repeating task,
|
||||||
|
* prevent its further execution.
|
||||||
|
*
|
||||||
|
* @param id the id of the task to cancel
|
||||||
|
*/
|
||||||
|
void cancel(int id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancel a task to prevent it from executing, or if its a repeating task,
|
||||||
|
* prevent its further execution.
|
||||||
|
*
|
||||||
|
* @param task the task to cancel
|
||||||
|
*/
|
||||||
|
void cancel(ScheduledTask task);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancel all tasks owned by this plugin, this preventing them from being
|
||||||
|
* executed hereon in.
|
||||||
|
*
|
||||||
|
* @param plugin the plugin owning the tasks to be cancelled
|
||||||
|
* @return the number of tasks cancelled by this method
|
||||||
|
*/
|
||||||
|
int cancel(Plugin plugin);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedule a task to be executed asynchronously. The task will commence
|
||||||
|
* running as soon as this method returns.
|
||||||
|
*
|
||||||
|
* @param owner the plugin owning this task
|
||||||
|
* @param task the task to run
|
||||||
|
* @return the scheduled task
|
||||||
|
*/
|
||||||
|
ScheduledTask runAsync(Plugin owner, Runnable task);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedules a task to be executed asynchronously after the specified delay
|
||||||
|
* is up.
|
||||||
|
*
|
||||||
|
* @param owner the plugin owning this task
|
||||||
|
* @param task the task to run
|
||||||
|
* @param delay the delay before this task will be executed
|
||||||
|
* @param unit the unit in which the delay will be measured
|
||||||
|
* @return the scheduled task
|
||||||
|
*/
|
||||||
|
ScheduledTask schedule(Plugin owner, Runnable task, long delay, TimeUnit unit);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedules a task to be executed asynchronously after the specified delay
|
||||||
|
* is up. The scheduled task will continue running at the specified
|
||||||
|
* interval. The interval will not begin to count down until the last task
|
||||||
|
* invocation is complete.
|
||||||
|
*
|
||||||
|
* @param owner the plugin owning this task
|
||||||
|
* @param task the task to run
|
||||||
|
* @param delay the delay in milliseconds before this task will be executed
|
||||||
|
* @param period the interval before subsequent executions of this task
|
||||||
|
* @param unit the unit in which the delay and period will be measured
|
||||||
|
* @return the scheduled task
|
||||||
|
*/
|
||||||
|
ScheduledTask schedule(Plugin owner, Runnable task, long delay, long period, TimeUnit unit);
|
||||||
|
}
|
20
api/src/main/java/net/md_5/bungee/api/score/Objective.java
Normal file
20
api/src/main/java/net/md_5/bungee/api/score/Objective.java
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package net.md_5.bungee.api.score;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an objective entry.
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class Objective
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of the objective.
|
||||||
|
*/
|
||||||
|
private final String name;
|
||||||
|
/**
|
||||||
|
* Value of the objective.
|
||||||
|
*/
|
||||||
|
private final String value; // displayName
|
||||||
|
}
|
10
api/src/main/java/net/md_5/bungee/api/score/Position.java
Normal file
10
api/src/main/java/net/md_5/bungee/api/score/Position.java
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package net.md_5.bungee.api.score;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents locations for a scoreboard to be displayed.
|
||||||
|
*/
|
||||||
|
public enum Position
|
||||||
|
{
|
||||||
|
|
||||||
|
LIST, SIDEBAR, BELOW;
|
||||||
|
}
|
24
api/src/main/java/net/md_5/bungee/api/score/Score.java
Normal file
24
api/src/main/java/net/md_5/bungee/api/score/Score.java
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package net.md_5.bungee.api.score;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a scoreboard score entry.
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class Score
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name to be displayed in the list.
|
||||||
|
*/
|
||||||
|
private final String itemName; // Player
|
||||||
|
/**
|
||||||
|
* Unique name of the score.
|
||||||
|
*/
|
||||||
|
private final String scoreName; // Score
|
||||||
|
/**
|
||||||
|
* Value of the score.
|
||||||
|
*/
|
||||||
|
private final int value;
|
||||||
|
}
|
100
api/src/main/java/net/md_5/bungee/api/score/Scoreboard.java
Normal file
100
api/src/main/java/net/md_5/bungee/api/score/Scoreboard.java
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
package net.md_5.bungee.api.score;
|
||||||
|
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class Scoreboard
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unique name for this scoreboard.
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
/**
|
||||||
|
* Position of this scoreboard.
|
||||||
|
*/
|
||||||
|
private Position position;
|
||||||
|
/**
|
||||||
|
* Objectives for this scoreboard.
|
||||||
|
*/
|
||||||
|
private final Map<String, Objective> objectives = new HashMap<>();
|
||||||
|
/**
|
||||||
|
* Scores for this scoreboard.
|
||||||
|
*/
|
||||||
|
private final Map<String, Score> scores = new HashMap<>();
|
||||||
|
/**
|
||||||
|
* Teams on this board.
|
||||||
|
*/
|
||||||
|
private final Map<String, Team> teams = new HashMap<>();
|
||||||
|
|
||||||
|
public Collection<Objective> getObjectives()
|
||||||
|
{
|
||||||
|
return Collections.unmodifiableCollection( objectives.values() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<Score> getScores()
|
||||||
|
{
|
||||||
|
return Collections.unmodifiableCollection( scores.values() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<Team> getTeams()
|
||||||
|
{
|
||||||
|
return Collections.unmodifiableCollection( teams.values() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addObjective(Objective objective)
|
||||||
|
{
|
||||||
|
Preconditions.checkNotNull( objective, "objective" );
|
||||||
|
Preconditions.checkArgument( !objectives.containsKey( objective.getName() ), "Objective %s already exists in this scoreboard", objective.getName() );
|
||||||
|
objectives.put( objective.getName(), objective );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addScore(Score score)
|
||||||
|
{
|
||||||
|
Preconditions.checkNotNull( score, "score" );
|
||||||
|
scores.put( score.getItemName(), score );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addTeam(Team team)
|
||||||
|
{
|
||||||
|
Preconditions.checkNotNull( team, "team" );
|
||||||
|
Preconditions.checkArgument( !teams.containsKey( team.getName() ), "Team %s already exists in this scoreboard", team.getName() );
|
||||||
|
teams.put( team.getName(), team );
|
||||||
|
}
|
||||||
|
|
||||||
|
public Team getTeam(String name)
|
||||||
|
{
|
||||||
|
return teams.get( name );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeObjective(String objectiveName)
|
||||||
|
{
|
||||||
|
objectives.remove( objectiveName );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeScore(String scoreName)
|
||||||
|
{
|
||||||
|
scores.remove( scoreName );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeTeam(String teamName)
|
||||||
|
{
|
||||||
|
teams.remove( teamName );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear()
|
||||||
|
{
|
||||||
|
name = null;
|
||||||
|
position = null;
|
||||||
|
objectives.clear();
|
||||||
|
scores.clear();
|
||||||
|
teams.clear();
|
||||||
|
}
|
||||||
|
}
|
36
api/src/main/java/net/md_5/bungee/api/score/Team.java
Normal file
36
api/src/main/java/net/md_5/bungee/api/score/Team.java
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
package net.md_5.bungee.api.score;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NonNull;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class Team
|
||||||
|
{
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
private final String name;
|
||||||
|
private String displayName;
|
||||||
|
private String prefix;
|
||||||
|
private String suffix;
|
||||||
|
private boolean friendlyFire;
|
||||||
|
private Set<String> players = new HashSet<>();
|
||||||
|
|
||||||
|
public Collection<String> getPlayers()
|
||||||
|
{
|
||||||
|
return Collections.unmodifiableSet( players );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addPlayer(String name)
|
||||||
|
{
|
||||||
|
players.add( name );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removePlayer(String name)
|
||||||
|
{
|
||||||
|
players.remove( name );
|
||||||
|
}
|
||||||
|
}
|
60
api/src/main/java/net/md_5/bungee/api/tab/CustomTabList.java
Normal file
60
api/src/main/java/net/md_5/bungee/api/tab/CustomTabList.java
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
package net.md_5.bungee.api.tab;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a custom tab list, which may have slots manipulated.
|
||||||
|
*/
|
||||||
|
public interface CustomTabList extends TabListHandler
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Blank out this tab list and update immediately.
|
||||||
|
*/
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the columns in this list.
|
||||||
|
*
|
||||||
|
* @return the width of this list
|
||||||
|
*/
|
||||||
|
int getColumns();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the rows in this list.
|
||||||
|
*
|
||||||
|
* @return the height of this list
|
||||||
|
*/
|
||||||
|
int getRows();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the total size of this list.
|
||||||
|
*
|
||||||
|
* @return {@link #getRows()} * {@link #getColumns()}
|
||||||
|
*/
|
||||||
|
int getSize();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the text in the specified slot and update immediately.
|
||||||
|
*
|
||||||
|
* @param row the row to set
|
||||||
|
* @param column the column to set
|
||||||
|
* @param text the text to set
|
||||||
|
* @return the padded text
|
||||||
|
*/
|
||||||
|
String setSlot(int row, int column, String text);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the text in the specified slot.
|
||||||
|
*
|
||||||
|
* @param row the row to set
|
||||||
|
* @param column the column to set
|
||||||
|
* @param text the text to set
|
||||||
|
* @param update whether or not to invoke {@link #update()} upon completion
|
||||||
|
* @return the padded text
|
||||||
|
*/
|
||||||
|
String setSlot(int row, int column, String text, boolean update);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flush all queued changes to the user.
|
||||||
|
*/
|
||||||
|
void update();
|
||||||
|
}
|
@@ -0,0 +1,39 @@
|
|||||||
|
package net.md_5.bungee.api.tab;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||||
|
|
||||||
|
@NoArgsConstructor
|
||||||
|
public abstract class TabListAdapter implements TabListHandler
|
||||||
|
{
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private ProxiedPlayer player;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(ProxiedPlayer player)
|
||||||
|
{
|
||||||
|
this.player = player;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onConnect()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDisconnect()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onServerChange()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPingChange(int ping)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@@ -1,23 +1,30 @@
|
|||||||
package net.md_5.bungee.api;
|
package net.md_5.bungee.api.tab;
|
||||||
|
|
||||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||||
|
|
||||||
public interface TabListHandler
|
public interface TabListHandler
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called so that this class may set member fields to keep track of its
|
||||||
|
* internal state. You should not do any packet sending or manipulation of
|
||||||
|
* the passed player, other than storing it.
|
||||||
|
*
|
||||||
|
* @param player the player to be associated with this list
|
||||||
|
*/
|
||||||
|
void init(ProxiedPlayer player);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when this player first connects to the proxy.
|
||||||
|
*/
|
||||||
|
void onConnect();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when a player first connects to the proxy.
|
* Called when a player first connects to the proxy.
|
||||||
*
|
*
|
||||||
* @param player the connecting player
|
* @param player the connecting player
|
||||||
*/
|
*/
|
||||||
public void onConnect(ProxiedPlayer player);
|
void onServerChange();
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when a player changes their connected server.
|
|
||||||
*
|
|
||||||
* @param player the player who changed servers
|
|
||||||
*/
|
|
||||||
public void onServerChange(ProxiedPlayer player);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when a players ping changes. The new ping will have not updated in
|
* Called when a players ping changes. The new ping will have not updated in
|
||||||
@@ -26,14 +33,14 @@ public interface TabListHandler
|
|||||||
* @param player the player who's ping changed
|
* @param player the player who's ping changed
|
||||||
* @param ping the player's new ping.
|
* @param ping the player's new ping.
|
||||||
*/
|
*/
|
||||||
public void onPingChange(ProxiedPlayer player, int ping);
|
void onPingChange(int ping);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when a player disconnects.
|
* Called when a player disconnects.
|
||||||
*
|
*
|
||||||
* @param player the disconnected player
|
* @param player the disconnected player
|
||||||
*/
|
*/
|
||||||
public void onDisconnect(ProxiedPlayer player);
|
void onDisconnect();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when a list update packet is sent from server to client.
|
* Called when a list update packet is sent from server to client.
|
||||||
@@ -44,5 +51,5 @@ public interface TabListHandler
|
|||||||
* @param ping ping of the subject player
|
* @param ping ping of the subject player
|
||||||
* @return whether to send the packet to the client
|
* @return whether to send the packet to the client
|
||||||
*/
|
*/
|
||||||
public boolean onListUpdate(ProxiedPlayer player, String name, boolean online, int ping);
|
boolean onListUpdate(String name, boolean online, int ping);
|
||||||
}
|
}
|
31
config/nb-configuration.xml
Normal file
31
config/nb-configuration.xml
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project-shared-configuration>
|
||||||
|
<!--
|
||||||
|
This file contains additional configuration written by modules in the NetBeans IDE.
|
||||||
|
The configuration is intended to be shared among all the users of project and
|
||||||
|
therefore it is assumed to be part of version control checkout.
|
||||||
|
Without this configuration present, some functionality in the IDE may be limited or fail altogether.
|
||||||
|
-->
|
||||||
|
<properties xmlns="http://www.netbeans.org/ns/maven-properties-data/1">
|
||||||
|
<!--
|
||||||
|
Properties that influence various parts of the IDE, especially code formatting and the like.
|
||||||
|
You can copy and paste the single properties, into the pom.xml file and the IDE will pick them up.
|
||||||
|
That way multiple projects can share the same settings (useful for formatting rules for example).
|
||||||
|
Any value defined here will override the pom.xml file value but is only applicable to the current project.
|
||||||
|
-->
|
||||||
|
<org-netbeans-modules-editor-indent.CodeStyle.usedProfile>project</org-netbeans-modules-editor-indent.CodeStyle.usedProfile>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.classDeclBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.classDeclBracePlacement>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.otherBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.otherBracePlacement>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.methodDeclBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.methodDeclBracePlacement>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinMethodCallParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinMethodCallParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSwitchParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSwitchParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinCatchParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinCatchParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinTryParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinTryParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSynchronizedParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSynchronizedParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinArrayInitBrackets>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinArrayInitBrackets>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinWhileParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinWhileParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinIfParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinIfParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinForParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinForParens>
|
||||||
|
</properties>
|
||||||
|
</project-shared-configuration>
|
31
event/nb-configuration.xml
Normal file
31
event/nb-configuration.xml
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project-shared-configuration>
|
||||||
|
<!--
|
||||||
|
This file contains additional configuration written by modules in the NetBeans IDE.
|
||||||
|
The configuration is intended to be shared among all the users of project and
|
||||||
|
therefore it is assumed to be part of version control checkout.
|
||||||
|
Without this configuration present, some functionality in the IDE may be limited or fail altogether.
|
||||||
|
-->
|
||||||
|
<properties xmlns="http://www.netbeans.org/ns/maven-properties-data/1">
|
||||||
|
<!--
|
||||||
|
Properties that influence various parts of the IDE, especially code formatting and the like.
|
||||||
|
You can copy and paste the single properties, into the pom.xml file and the IDE will pick them up.
|
||||||
|
That way multiple projects can share the same settings (useful for formatting rules for example).
|
||||||
|
Any value defined here will override the pom.xml file value but is only applicable to the current project.
|
||||||
|
-->
|
||||||
|
<org-netbeans-modules-editor-indent.CodeStyle.usedProfile>project</org-netbeans-modules-editor-indent.CodeStyle.usedProfile>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.classDeclBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.classDeclBracePlacement>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.otherBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.otherBracePlacement>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.methodDeclBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.methodDeclBracePlacement>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinMethodCallParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinMethodCallParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSwitchParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSwitchParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinCatchParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinCatchParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinTryParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinTryParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSynchronizedParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSynchronizedParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinArrayInitBrackets>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinArrayInitBrackets>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinWhileParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinWhileParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinIfParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinIfParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinForParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinForParens>
|
||||||
|
</properties>
|
||||||
|
</project-shared-configuration>
|
29
event/pom.xml
Normal file
29
event/pom.xml
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>net.md-5</groupId>
|
||||||
|
<artifactId>bungeecord-parent</artifactId>
|
||||||
|
<version>1.5-SNAPSHOT</version>
|
||||||
|
<relativePath>../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<groupId>net.md-5</groupId>
|
||||||
|
<artifactId>bungeecord-event</artifactId>
|
||||||
|
<version>1.5-SNAPSHOT</version>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<name>BungeeCord-Event</name>
|
||||||
|
<description>Generic java event dispatching API intended for use with BungeeCord</description>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<version>4.11</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
163
event/src/main/java/net/md_5/bungee/event/EventBus.java
Normal file
163
event/src/main/java/net/md_5/bungee/event/EventBus.java
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
package net.md_5.bungee.event;
|
||||||
|
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.locks.ReadWriteLock;
|
||||||
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
public class EventBus
|
||||||
|
{
|
||||||
|
|
||||||
|
private final Map<Class<?>, Map<Object, Method[]>> eventToHandler = new HashMap<>();
|
||||||
|
private final ReadWriteLock lock = new ReentrantReadWriteLock();
|
||||||
|
private final Logger logger;
|
||||||
|
private final Class<? extends Annotation>[] annotations;
|
||||||
|
|
||||||
|
public EventBus()
|
||||||
|
{
|
||||||
|
this( null, (Class<? extends Annotation>[]) null );
|
||||||
|
}
|
||||||
|
|
||||||
|
public EventBus(Logger logger)
|
||||||
|
{
|
||||||
|
this( logger, (Class<? extends Annotation>[]) null );
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public EventBus(Class<? extends Annotation>... annotations)
|
||||||
|
{
|
||||||
|
this( null, annotations );
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public EventBus(Logger logger, Class<? extends Annotation>... annotations)
|
||||||
|
{
|
||||||
|
this.logger = ( logger == null ) ? Logger.getGlobal() : logger;
|
||||||
|
this.annotations = ( annotations == null || annotations.length == 0 ) ? new Class[]
|
||||||
|
{
|
||||||
|
EventHandler.class
|
||||||
|
} : annotations;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void post(Object event)
|
||||||
|
{
|
||||||
|
lock.readLock().lock();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Map<Object, Method[]> handlers = eventToHandler.get( event.getClass() );
|
||||||
|
if ( handlers != null )
|
||||||
|
{
|
||||||
|
for ( Map.Entry<Object, Method[]> handler : handlers.entrySet() )
|
||||||
|
{
|
||||||
|
for ( Method method : handler.getValue() )
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
method.invoke( handler.getKey(), event );
|
||||||
|
} catch ( IllegalAccessException ex )
|
||||||
|
{
|
||||||
|
throw new Error( "Method became inaccessible: " + event, ex );
|
||||||
|
} catch ( IllegalArgumentException ex )
|
||||||
|
{
|
||||||
|
throw new Error( "Method rejected target/argument: " + event, ex );
|
||||||
|
} catch ( InvocationTargetException ex )
|
||||||
|
{
|
||||||
|
logger.log( Level.WARNING, MessageFormat.format( "Error dispatching event {0} to listener {1}", event, handler.getKey() ), ex.getCause() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally
|
||||||
|
{
|
||||||
|
lock.readLock().unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<Class<?>, Set<Method>> findHandlers(Object listener)
|
||||||
|
{
|
||||||
|
Map<Class<?>, Set<Method>> handler = new HashMap<>();
|
||||||
|
for ( Method m : listener.getClass().getDeclaredMethods() )
|
||||||
|
{
|
||||||
|
for ( Class<? extends Annotation> annotation : annotations )
|
||||||
|
{
|
||||||
|
if ( m.isAnnotationPresent( annotation ) )
|
||||||
|
{
|
||||||
|
Class<?>[] params = m.getParameterTypes();
|
||||||
|
if ( params.length != 1 )
|
||||||
|
{
|
||||||
|
logger.log( Level.INFO, "Method {0} in class {1} annotated with {2} does not have single argument", new Object[]
|
||||||
|
{
|
||||||
|
m, listener.getClass(), annotation
|
||||||
|
} );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<Method> existing = handler.get( params[0] );
|
||||||
|
if ( existing == null )
|
||||||
|
{
|
||||||
|
existing = new HashSet<>();
|
||||||
|
handler.put( params[0], existing );
|
||||||
|
}
|
||||||
|
existing.add( m );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void register(Object listener)
|
||||||
|
{
|
||||||
|
Map<Class<?>, Set<Method>> handler = findHandlers( listener );
|
||||||
|
lock.writeLock().lock();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
for ( Map.Entry<Class<?>, Set<Method>> e : handler.entrySet() )
|
||||||
|
{
|
||||||
|
Map<Object, Method[]> a = eventToHandler.get( e.getKey() );
|
||||||
|
if ( a == null )
|
||||||
|
{
|
||||||
|
a = new HashMap<>();
|
||||||
|
eventToHandler.put( e.getKey(), a );
|
||||||
|
}
|
||||||
|
Method[] baked = new Method[ e.getValue().size() ];
|
||||||
|
a.put( listener, e.getValue().toArray( baked ) );
|
||||||
|
}
|
||||||
|
} finally
|
||||||
|
{
|
||||||
|
lock.writeLock().unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unregister(Object listener)
|
||||||
|
{
|
||||||
|
Map<Class<?>, Set<Method>> handler = findHandlers( listener );
|
||||||
|
lock.writeLock().lock();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
for ( Map.Entry<Class<?>, Set<Method>> e : handler.entrySet() )
|
||||||
|
{
|
||||||
|
Map<Object, Method[]> a = eventToHandler.get( e.getKey() );
|
||||||
|
if ( a != null )
|
||||||
|
{
|
||||||
|
a.remove( listener );
|
||||||
|
if ( a.isEmpty() )
|
||||||
|
{
|
||||||
|
eventToHandler.remove( e.getKey() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally
|
||||||
|
{
|
||||||
|
lock.writeLock().unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12
event/src/main/java/net/md_5/bungee/event/EventHandler.java
Normal file
12
event/src/main/java/net/md_5/bungee/event/EventHandler.java
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
package net.md_5.bungee.event;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
public @interface EventHandler
|
||||||
|
{
|
||||||
|
}
|
42
event/src/test/java/net/md_5/bungee/event/EventBusTest.java
Normal file
42
event/src/test/java/net/md_5/bungee/event/EventBusTest.java
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package net.md_5.bungee.event;
|
||||||
|
|
||||||
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class EventBusTest
|
||||||
|
{
|
||||||
|
|
||||||
|
private final EventBus bus = new EventBus();
|
||||||
|
private final CountDownLatch latch = new CountDownLatch( 2 );
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNestedEvents()
|
||||||
|
{
|
||||||
|
bus.register( this );
|
||||||
|
bus.post( new FirstEvent() );
|
||||||
|
Assert.assertEquals( latch.getCount(), 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void firstListener(FirstEvent event)
|
||||||
|
{
|
||||||
|
bus.post( new SecondEvent() );
|
||||||
|
Assert.assertEquals( latch.getCount(), 1 );
|
||||||
|
latch.countDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void secondListener(SecondEvent event)
|
||||||
|
{
|
||||||
|
latch.countDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class FirstEvent
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class SecondEvent
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
31
nb-configuration.xml
Normal file
31
nb-configuration.xml
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project-shared-configuration>
|
||||||
|
<!--
|
||||||
|
This file contains additional configuration written by modules in the NetBeans IDE.
|
||||||
|
The configuration is intended to be shared among all the users of project and
|
||||||
|
therefore it is assumed to be part of version control checkout.
|
||||||
|
Without this configuration present, some functionality in the IDE may be limited or fail altogether.
|
||||||
|
-->
|
||||||
|
<properties xmlns="http://www.netbeans.org/ns/maven-properties-data/1">
|
||||||
|
<!--
|
||||||
|
Properties that influence various parts of the IDE, especially code formatting and the like.
|
||||||
|
You can copy and paste the single properties, into the pom.xml file and the IDE will pick them up.
|
||||||
|
That way multiple projects can share the same settings (useful for formatting rules for example).
|
||||||
|
Any value defined here will override the pom.xml file value but is only applicable to the current project.
|
||||||
|
-->
|
||||||
|
<org-netbeans-modules-editor-indent.CodeStyle.usedProfile>project</org-netbeans-modules-editor-indent.CodeStyle.usedProfile>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.classDeclBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.classDeclBracePlacement>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.otherBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.otherBracePlacement>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.methodDeclBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.methodDeclBracePlacement>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinMethodCallParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinMethodCallParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSwitchParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSwitchParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinCatchParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinCatchParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinTryParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinTryParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSynchronizedParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSynchronizedParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinArrayInitBrackets>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinArrayInitBrackets>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinWhileParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinWhileParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinIfParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinIfParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinForParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinForParens>
|
||||||
|
</properties>
|
||||||
|
</project-shared-configuration>
|
16
pom.xml
16
pom.xml
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
<groupId>net.md-5</groupId>
|
<groupId>net.md-5</groupId>
|
||||||
<artifactId>bungeecord-parent</artifactId>
|
<artifactId>bungeecord-parent</artifactId>
|
||||||
<version>1.4.7-SNAPSHOT</version>
|
<version>1.5-SNAPSHOT</version>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
|
|
||||||
<name>BungeeCord</name>
|
<name>BungeeCord</name>
|
||||||
@@ -38,6 +38,7 @@
|
|||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
<module>api</module>
|
<module>api</module>
|
||||||
|
<module>event</module>
|
||||||
<module>protocol</module>
|
<module>protocol</module>
|
||||||
<module>proxy</module>
|
<module>proxy</module>
|
||||||
</modules>
|
</modules>
|
||||||
@@ -57,15 +58,22 @@
|
|||||||
</ciManagement>
|
</ciManagement>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
|
||||||
<build.number>unknown</build.number>
|
<build.number>unknown</build.number>
|
||||||
|
<netty.version>4.0.0.CR7</netty.version>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<version>4.11</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.projectlombok</groupId>
|
<groupId>org.projectlombok</groupId>
|
||||||
<artifactId>lombok</artifactId>
|
<artifactId>lombok</artifactId>
|
||||||
<version>0.11.6</version>
|
<version>0.11.8</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
@@ -92,7 +100,7 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
<version>3.0</version>
|
<version>2.5.1</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<source>1.7</source>
|
<source>1.7</source>
|
||||||
<target>1.7</target>
|
<target>1.7</target>
|
||||||
|
31
protocol/nb-configuration.xml
Normal file
31
protocol/nb-configuration.xml
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project-shared-configuration>
|
||||||
|
<!--
|
||||||
|
This file contains additional configuration written by modules in the NetBeans IDE.
|
||||||
|
The configuration is intended to be shared among all the users of project and
|
||||||
|
therefore it is assumed to be part of version control checkout.
|
||||||
|
Without this configuration present, some functionality in the IDE may be limited or fail altogether.
|
||||||
|
-->
|
||||||
|
<properties xmlns="http://www.netbeans.org/ns/maven-properties-data/1">
|
||||||
|
<!--
|
||||||
|
Properties that influence various parts of the IDE, especially code formatting and the like.
|
||||||
|
You can copy and paste the single properties, into the pom.xml file and the IDE will pick them up.
|
||||||
|
That way multiple projects can share the same settings (useful for formatting rules for example).
|
||||||
|
Any value defined here will override the pom.xml file value but is only applicable to the current project.
|
||||||
|
-->
|
||||||
|
<org-netbeans-modules-editor-indent.CodeStyle.usedProfile>project</org-netbeans-modules-editor-indent.CodeStyle.usedProfile>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.classDeclBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.classDeclBracePlacement>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.otherBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.otherBracePlacement>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.methodDeclBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.methodDeclBracePlacement>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinMethodCallParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinMethodCallParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSwitchParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSwitchParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinCatchParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinCatchParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinTryParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinTryParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSynchronizedParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSynchronizedParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinArrayInitBrackets>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinArrayInitBrackets>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinWhileParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinWhileParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinIfParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinIfParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinForParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinForParens>
|
||||||
|
</properties>
|
||||||
|
</project-shared-configuration>
|
@@ -6,15 +6,24 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>net.md-5</groupId>
|
<groupId>net.md-5</groupId>
|
||||||
<artifactId>bungeecord-parent</artifactId>
|
<artifactId>bungeecord-parent</artifactId>
|
||||||
<version>1.4.7-SNAPSHOT</version>
|
<version>1.5-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<groupId>net.md-5</groupId>
|
<groupId>net.md-5</groupId>
|
||||||
<artifactId>bungeecord-protocol</artifactId>
|
<artifactId>bungeecord-protocol</artifactId>
|
||||||
<version>1.4.7-SNAPSHOT</version>
|
<version>1.5-SNAPSHOT</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>BungeeCord-Protocol</name>
|
<name>BungeeCord-Protocol</name>
|
||||||
<description>Minimal implementation of the Minecraft protocol for use in BungeeCord</description>
|
<description>Minimal implementation of the Minecraft protocol for use in BungeeCord</description>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.netty</groupId>
|
||||||
|
<artifactId>netty-buffer</artifactId>
|
||||||
|
<version>${netty.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
|
33
protocol/src/main/java/net/md_5/bungee/protocol/Forge.java
Normal file
33
protocol/src/main/java/net/md_5/bungee/protocol/Forge.java
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
package net.md_5.bungee.protocol;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import lombok.Getter;
|
||||||
|
import net.md_5.bungee.protocol.packet.DefinedPacket;
|
||||||
|
import net.md_5.bungee.protocol.packet.forge.Forge1Login;
|
||||||
|
import net.md_5.bungee.protocol.skip.PacketReader;
|
||||||
|
|
||||||
|
public class Forge extends Vanilla
|
||||||
|
{
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private static final Forge instance = new Forge();
|
||||||
|
|
||||||
|
public Forge()
|
||||||
|
{
|
||||||
|
classes[0x01] = Forge1Login.class;
|
||||||
|
skipper = new PacketReader( this ); // TODO: :(
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DefinedPacket read(short packetId, ByteBuf buf)
|
||||||
|
{
|
||||||
|
int start = buf.readerIndex();
|
||||||
|
DefinedPacket packet = read( packetId, buf, this );
|
||||||
|
if ( buf.readerIndex() == start )
|
||||||
|
{
|
||||||
|
packet = super.read( packetId, buf );
|
||||||
|
}
|
||||||
|
|
||||||
|
return packet;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,7 @@
|
|||||||
|
package net.md_5.bungee.protocol;
|
||||||
|
|
||||||
|
public enum OpCode
|
||||||
|
{
|
||||||
|
|
||||||
|
BOOLEAN, BULK_CHUNK, BYTE, BYTE_INT, DOUBLE, FLOAT, INT, INT_3, INT_BYTE, ITEM, LONG, METADATA, OPTIONAL_MOTION, SHORT, SHORT_BYTE, SHORT_ITEM, STRING, USHORT_BYTE
|
||||||
|
}
|
@@ -0,0 +1,20 @@
|
|||||||
|
package net.md_5.bungee.protocol;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import net.md_5.bungee.protocol.packet.DefinedPacket;
|
||||||
|
import net.md_5.bungee.protocol.skip.PacketReader;
|
||||||
|
|
||||||
|
public interface Protocol
|
||||||
|
{
|
||||||
|
|
||||||
|
PacketReader getSkipper();
|
||||||
|
|
||||||
|
DefinedPacket read(short packetId, ByteBuf buf);
|
||||||
|
|
||||||
|
OpCode[][] getOpCodes();
|
||||||
|
|
||||||
|
Class<? extends DefinedPacket>[] getClasses();
|
||||||
|
|
||||||
|
Constructor<? extends DefinedPacket>[] getConstructors();
|
||||||
|
}
|
@@ -1,39 +1,128 @@
|
|||||||
package net.md_5.mendax;
|
package net.md_5.bungee.protocol;
|
||||||
|
|
||||||
import static net.md_5.mendax.PacketDefinitions.OpCode.*;
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import lombok.Getter;
|
||||||
|
import static net.md_5.bungee.protocol.OpCode.*;
|
||||||
|
import net.md_5.bungee.protocol.packet.DefinedPacket;
|
||||||
|
import net.md_5.bungee.protocol.packet.Packet0KeepAlive;
|
||||||
|
import net.md_5.bungee.protocol.packet.Packet1Login;
|
||||||
|
import net.md_5.bungee.protocol.packet.Packet2Handshake;
|
||||||
|
import net.md_5.bungee.protocol.packet.Packet3Chat;
|
||||||
|
import net.md_5.bungee.protocol.packet.Packet9Respawn;
|
||||||
|
import net.md_5.bungee.protocol.packet.PacketC9PlayerListItem;
|
||||||
|
import net.md_5.bungee.protocol.packet.PacketCCSettings;
|
||||||
|
import net.md_5.bungee.protocol.packet.PacketCDClientStatus;
|
||||||
|
import net.md_5.bungee.protocol.packet.PacketCEScoreboardObjective;
|
||||||
|
import net.md_5.bungee.protocol.packet.PacketCFScoreboardScore;
|
||||||
|
import net.md_5.bungee.protocol.packet.PacketD0DisplayScoreboard;
|
||||||
|
import net.md_5.bungee.protocol.packet.PacketD1Team;
|
||||||
|
import net.md_5.bungee.protocol.packet.PacketFAPluginMessage;
|
||||||
|
import net.md_5.bungee.protocol.packet.PacketFCEncryptionResponse;
|
||||||
|
import net.md_5.bungee.protocol.packet.PacketFDEncryptionRequest;
|
||||||
|
import net.md_5.bungee.protocol.packet.PacketFEPing;
|
||||||
|
import net.md_5.bungee.protocol.packet.PacketFFKick;
|
||||||
|
import net.md_5.bungee.protocol.skip.PacketReader;
|
||||||
|
|
||||||
public class PacketDefinitions
|
public class Vanilla implements Protocol
|
||||||
{
|
{
|
||||||
|
|
||||||
private static final int MAX_PACKET = 256;
|
public static final byte PROTOCOL_VERSION = 61;
|
||||||
public static final OpCode[][] opCodes = new OpCode[ MAX_PACKET * 2 ][];
|
public static final String GAME_VERSION = "1.5.2";
|
||||||
public static final int VANILLA_PROTOCOL = 0;
|
@Getter
|
||||||
public static final int FORGE_PROTOCOL = MAX_PACKET;
|
private static final Vanilla instance = new Vanilla();
|
||||||
|
/*========================================================================*/
|
||||||
|
@Getter
|
||||||
|
private final OpCode[][] opCodes = new OpCode[ 256 ][];
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Getter
|
||||||
|
protected Class<? extends DefinedPacket>[] classes = new Class[ 256 ];
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Getter
|
||||||
|
private Constructor<? extends DefinedPacket>[] constructors = new Constructor[ 256 ];
|
||||||
|
@Getter
|
||||||
|
protected PacketReader skipper;
|
||||||
|
/*========================================================================*/
|
||||||
|
|
||||||
public enum OpCode
|
public Vanilla()
|
||||||
{
|
{
|
||||||
|
classes[0x00] = Packet0KeepAlive.class;
|
||||||
BOOLEAN, BULK_CHUNK, BYTE, BYTE_INT, DOUBLE, FLOAT, INT, INT_3, INT_BYTE, ITEM, LONG, METADATA, OPTIONAL_MOTION, SHORT, SHORT_BYTE, SHORT_ITEM, STRING, USHORT_BYTE
|
classes[0x01] = Packet1Login.class;
|
||||||
|
classes[0x02] = Packet2Handshake.class;
|
||||||
|
classes[0x03] = Packet3Chat.class;
|
||||||
|
classes[0x09] = Packet9Respawn.class;
|
||||||
|
classes[0xC9] = PacketC9PlayerListItem.class;
|
||||||
|
classes[0xCC] = PacketCCSettings.class;
|
||||||
|
classes[0xCD] = PacketCDClientStatus.class;
|
||||||
|
classes[0xCE] = PacketCEScoreboardObjective.class;
|
||||||
|
classes[0xCF] = PacketCFScoreboardScore.class;
|
||||||
|
classes[0xD0] = PacketD0DisplayScoreboard.class;
|
||||||
|
classes[0xD1] = PacketD1Team.class;
|
||||||
|
classes[0xFA] = PacketFAPluginMessage.class;
|
||||||
|
classes[0xFC] = PacketFCEncryptionResponse.class;
|
||||||
|
classes[0xFD] = PacketFDEncryptionRequest.class;
|
||||||
|
classes[0xFE] = PacketFEPing.class;
|
||||||
|
classes[0xFF] = PacketFFKick.class;
|
||||||
|
skipper = new PacketReader( this );
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
@Override
|
||||||
|
public DefinedPacket read(short packetId, ByteBuf buf)
|
||||||
{
|
{
|
||||||
opCodes[0x00] = new OpCode[]
|
int start = buf.readerIndex();
|
||||||
|
DefinedPacket packet = read( packetId, buf, this );
|
||||||
|
if ( buf.readerIndex() == start )
|
||||||
{
|
{
|
||||||
INT
|
throw new RuntimeException( "Unknown packet id " + packetId );
|
||||||
};
|
}
|
||||||
opCodes[0x01] = new OpCode[]
|
return packet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DefinedPacket read(short id, ByteBuf buf, Protocol protocol)
|
||||||
{
|
{
|
||||||
INT, STRING, BYTE, BYTE, BYTE, BYTE, BYTE
|
DefinedPacket packet = packet( id, protocol );
|
||||||
};
|
if ( packet != null )
|
||||||
opCodes[0x02] = new OpCode[]
|
|
||||||
{
|
{
|
||||||
BYTE, STRING, STRING, INT
|
packet.read( buf );
|
||||||
};
|
return packet;
|
||||||
opCodes[0x03] = new OpCode[]
|
}
|
||||||
|
protocol.getSkipper().tryRead( id, buf );
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DefinedPacket packet(short id, Protocol protocol)
|
||||||
|
{
|
||||||
|
DefinedPacket ret = null;
|
||||||
|
Class<? extends DefinedPacket> clazz = protocol.getClasses()[id];
|
||||||
|
|
||||||
|
if ( clazz != null )
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Constructor<? extends DefinedPacket> constructor = protocol.getConstructors()[id];
|
||||||
|
if ( constructor == null )
|
||||||
|
{
|
||||||
|
constructor = clazz.getDeclaredConstructor();
|
||||||
|
constructor.setAccessible( true );
|
||||||
|
protocol.getConstructors()[id] = constructor;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( constructor != null )
|
||||||
|
{
|
||||||
|
ret = constructor.newInstance();
|
||||||
|
}
|
||||||
|
} catch ( NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
STRING
|
|
||||||
};
|
|
||||||
opCodes[0x04] = new OpCode[]
|
opCodes[0x04] = new OpCode[]
|
||||||
{
|
{
|
||||||
LONG, LONG
|
LONG, LONG
|
||||||
@@ -54,10 +143,6 @@ public class PacketDefinitions
|
|||||||
{
|
{
|
||||||
SHORT, SHORT, FLOAT
|
SHORT, SHORT, FLOAT
|
||||||
};
|
};
|
||||||
opCodes[0x09] = new OpCode[]
|
|
||||||
{
|
|
||||||
INT, BYTE, BYTE, SHORT, STRING
|
|
||||||
};
|
|
||||||
opCodes[0x0A] = new OpCode[]
|
opCodes[0x0A] = new OpCode[]
|
||||||
{
|
{
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
@@ -214,6 +299,10 @@ public class PacketDefinitions
|
|||||||
{
|
{
|
||||||
STRING, INT, INT, INT, FLOAT, BYTE
|
STRING, INT, INT, INT, FLOAT, BYTE
|
||||||
};
|
};
|
||||||
|
opCodes[0x3F] = new OpCode[]
|
||||||
|
{
|
||||||
|
STRING, FLOAT, FLOAT, FLOAT, FLOAT, FLOAT, FLOAT, FLOAT, INT
|
||||||
|
};
|
||||||
opCodes[0x46] = new OpCode[]
|
opCodes[0x46] = new OpCode[]
|
||||||
{
|
{
|
||||||
BYTE, BYTE
|
BYTE, BYTE
|
||||||
@@ -224,7 +313,7 @@ public class PacketDefinitions
|
|||||||
};
|
};
|
||||||
opCodes[0x64] = new OpCode[]
|
opCodes[0x64] = new OpCode[]
|
||||||
{
|
{
|
||||||
BYTE, BYTE, STRING, BYTE
|
BYTE, BYTE, STRING, BYTE, BOOLEAN
|
||||||
};
|
};
|
||||||
opCodes[0x65] = new OpCode[]
|
opCodes[0x65] = new OpCode[]
|
||||||
{
|
{
|
||||||
@@ -278,10 +367,6 @@ public class PacketDefinitions
|
|||||||
{
|
{
|
||||||
INT, BYTE
|
INT, BYTE
|
||||||
};
|
};
|
||||||
opCodes[0xC9] = new OpCode[]
|
|
||||||
{
|
|
||||||
STRING, BOOLEAN, SHORT
|
|
||||||
};
|
|
||||||
opCodes[0xCA] = new OpCode[]
|
opCodes[0xCA] = new OpCode[]
|
||||||
{
|
{
|
||||||
BYTE, BYTE, BYTE
|
BYTE, BYTE, BYTE
|
||||||
@@ -290,37 +375,5 @@ public class PacketDefinitions
|
|||||||
{
|
{
|
||||||
STRING
|
STRING
|
||||||
};
|
};
|
||||||
opCodes[0xCC] = new OpCode[]
|
|
||||||
{
|
|
||||||
STRING, BYTE, BYTE, BYTE, BOOLEAN
|
|
||||||
};
|
|
||||||
opCodes[0xCD] = new OpCode[]
|
|
||||||
{
|
|
||||||
BYTE
|
|
||||||
};
|
|
||||||
opCodes[0xFA] = new OpCode[]
|
|
||||||
{
|
|
||||||
STRING, SHORT_BYTE
|
|
||||||
};
|
|
||||||
opCodes[0xFC] = new OpCode[]
|
|
||||||
{
|
|
||||||
SHORT_BYTE, SHORT_BYTE
|
|
||||||
};
|
|
||||||
opCodes[0xFD] = new OpCode[]
|
|
||||||
{
|
|
||||||
STRING, SHORT_BYTE, SHORT_BYTE
|
|
||||||
};
|
|
||||||
opCodes[0xFE] = new OpCode[]
|
|
||||||
{
|
|
||||||
}; // Should be byte, screw you too bitchy server admins!
|
|
||||||
opCodes[0xFF] = new OpCode[]
|
|
||||||
{
|
|
||||||
STRING
|
|
||||||
};
|
|
||||||
/*========================== Minecraft Forge ===========================*/
|
|
||||||
opCodes[0x01 + FORGE_PROTOCOL] = new OpCode[]
|
|
||||||
{
|
|
||||||
INT, STRING, BYTE, INT, BYTE, BYTE, BYTE
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,70 +1,73 @@
|
|||||||
package net.md_5.bungee.packet;
|
package net.md_5.bungee.protocol.packet;
|
||||||
|
|
||||||
public abstract class PacketHandler
|
public abstract class AbstractPacketHandler
|
||||||
{
|
{
|
||||||
|
|
||||||
private void nop(DefinedPacket packet)
|
|
||||||
{
|
|
||||||
throw new UnsupportedOperationException( "No handler defined for packet " + packet.getClass() );
|
|
||||||
}
|
|
||||||
|
|
||||||
public void handle(Packet0KeepAlive alive) throws Exception
|
public void handle(Packet0KeepAlive alive) throws Exception
|
||||||
{
|
{
|
||||||
nop( alive );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handle(Packet1Login login) throws Exception
|
public void handle(Packet1Login login) throws Exception
|
||||||
{
|
{
|
||||||
nop( login );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handle(Packet2Handshake handshake) throws Exception
|
public void handle(Packet2Handshake handshake) throws Exception
|
||||||
{
|
{
|
||||||
nop( handshake );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handle(Packet3Chat chat) throws Exception
|
public void handle(Packet3Chat chat) throws Exception
|
||||||
{
|
{
|
||||||
nop( chat );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handle(Packet9Respawn respawn) throws Exception
|
public void handle(Packet9Respawn respawn) throws Exception
|
||||||
{
|
{
|
||||||
nop( respawn );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handle(PacketC9PlayerListItem playerList) throws Exception
|
public void handle(PacketC9PlayerListItem playerList) throws Exception
|
||||||
{
|
{
|
||||||
nop( playerList );
|
}
|
||||||
|
|
||||||
|
public void handle(PacketCCSettings settings) throws Exception
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handle(PacketCDClientStatus clientStatus) throws Exception
|
public void handle(PacketCDClientStatus clientStatus) throws Exception
|
||||||
{
|
{
|
||||||
nop( clientStatus );
|
}
|
||||||
|
|
||||||
|
public void handle(PacketCEScoreboardObjective objective) throws Exception
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handle(PacketCFScoreboardScore score) throws Exception
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handle(PacketD0DisplayScoreboard displayScoreboard) throws Exception
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handle(PacketD1Team team) throws Exception
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handle(PacketFAPluginMessage pluginMessage) throws Exception
|
public void handle(PacketFAPluginMessage pluginMessage) throws Exception
|
||||||
{
|
{
|
||||||
nop( pluginMessage );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handle(PacketFCEncryptionResponse encryptResponse) throws Exception
|
public void handle(PacketFCEncryptionResponse encryptResponse) throws Exception
|
||||||
{
|
{
|
||||||
nop( encryptResponse );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handle(PacketFDEncryptionRequest encryptRequest) throws Exception
|
public void handle(PacketFDEncryptionRequest encryptRequest) throws Exception
|
||||||
{
|
{
|
||||||
nop( encryptRequest );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handle(PacketFEPing ping) throws Exception
|
public void handle(PacketFEPing ping) throws Exception
|
||||||
{
|
{
|
||||||
nop( ping );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void handle(PacketFFKick kick) throws Exception
|
public void handle(PacketFFKick kick) throws Exception
|
||||||
{
|
{
|
||||||
nop( kick );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -0,0 +1,69 @@
|
|||||||
|
package net.md_5.bungee.protocol.packet;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public abstract class DefinedPacket
|
||||||
|
{
|
||||||
|
|
||||||
|
private final int id;
|
||||||
|
|
||||||
|
public final int getId()
|
||||||
|
{
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeString(String s, ByteBuf buf)
|
||||||
|
{
|
||||||
|
// TODO: Check len - use Guava?
|
||||||
|
buf.writeShort( s.length() );
|
||||||
|
for ( char c : s.toCharArray() )
|
||||||
|
{
|
||||||
|
buf.writeChar( c );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String readString(ByteBuf buf)
|
||||||
|
{
|
||||||
|
// TODO: Check len - use Guava?
|
||||||
|
short len = buf.readShort();
|
||||||
|
char[] chars = new char[ len ];
|
||||||
|
for ( int i = 0; i < len; i++ )
|
||||||
|
{
|
||||||
|
chars[i] = buf.readChar();
|
||||||
|
}
|
||||||
|
return new String( chars );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeArray(byte[] b, ByteBuf buf)
|
||||||
|
{
|
||||||
|
// TODO: Check len - use Guava?
|
||||||
|
buf.writeShort( b.length );
|
||||||
|
buf.writeBytes( b );
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] readArray(ByteBuf buf)
|
||||||
|
{
|
||||||
|
// TODO: Check len - use Guava?
|
||||||
|
short len = buf.readShort();
|
||||||
|
byte[] ret = new byte[ len ];
|
||||||
|
buf.readBytes( ret );
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void read(ByteBuf buf);
|
||||||
|
|
||||||
|
public abstract void write(ByteBuf buf);
|
||||||
|
|
||||||
|
public abstract void handle(AbstractPacketHandler handler) throws Exception;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public abstract boolean equals(Object obj);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public abstract int hashCode();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public abstract String toString();
|
||||||
|
}
|
@@ -0,0 +1,38 @@
|
|||||||
|
package net.md_5.bungee.protocol.packet;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@ToString
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
public class Packet0KeepAlive extends DefinedPacket
|
||||||
|
{
|
||||||
|
|
||||||
|
private int randomId;
|
||||||
|
|
||||||
|
private Packet0KeepAlive()
|
||||||
|
{
|
||||||
|
super( 0x00 );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(ByteBuf buf)
|
||||||
|
{
|
||||||
|
randomId = buf.readInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(ByteBuf buf)
|
||||||
|
{
|
||||||
|
buf.writeInt( randomId );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(AbstractPacketHandler handler) throws Exception
|
||||||
|
{
|
||||||
|
handler.handle( this );
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,73 @@
|
|||||||
|
package net.md_5.bungee.protocol.packet;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@ToString
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
public class Packet1Login extends DefinedPacket
|
||||||
|
{
|
||||||
|
|
||||||
|
protected int entityId;
|
||||||
|
protected String levelType;
|
||||||
|
protected byte gameMode;
|
||||||
|
protected int dimension;
|
||||||
|
protected byte difficulty;
|
||||||
|
protected byte unused;
|
||||||
|
protected byte maxPlayers;
|
||||||
|
|
||||||
|
protected Packet1Login()
|
||||||
|
{
|
||||||
|
super( 0x01 );
|
||||||
|
}
|
||||||
|
|
||||||
|
public Packet1Login(int entityId, String levelType, byte gameMode, byte dimension, byte difficulty, byte unused, byte maxPlayers)
|
||||||
|
{
|
||||||
|
this( entityId, levelType, gameMode, (int) dimension, difficulty, unused, maxPlayers );
|
||||||
|
}
|
||||||
|
|
||||||
|
public Packet1Login(int entityId, String levelType, byte gameMode, int dimension, byte difficulty, byte unused, byte maxPlayers)
|
||||||
|
{
|
||||||
|
this();
|
||||||
|
this.entityId = entityId;
|
||||||
|
this.levelType = levelType;
|
||||||
|
this.gameMode = gameMode;
|
||||||
|
this.dimension = dimension;
|
||||||
|
this.difficulty = difficulty;
|
||||||
|
this.unused = unused;
|
||||||
|
this.maxPlayers = maxPlayers;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(ByteBuf buf)
|
||||||
|
{
|
||||||
|
entityId = buf.readInt();
|
||||||
|
levelType = readString( buf );
|
||||||
|
gameMode = buf.readByte();
|
||||||
|
dimension = buf.readByte();
|
||||||
|
difficulty = buf.readByte();
|
||||||
|
unused = buf.readByte();
|
||||||
|
maxPlayers = buf.readByte();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(ByteBuf buf)
|
||||||
|
{
|
||||||
|
buf.writeInt( entityId );
|
||||||
|
writeString( levelType, buf );
|
||||||
|
buf.writeByte( gameMode );
|
||||||
|
buf.writeByte( dimension );
|
||||||
|
buf.writeByte( difficulty );
|
||||||
|
buf.writeByte( unused );
|
||||||
|
buf.writeByte( maxPlayers );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(AbstractPacketHandler handler) throws Exception
|
||||||
|
{
|
||||||
|
handler.handle( this );
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,47 @@
|
|||||||
|
package net.md_5.bungee.protocol.packet;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@ToString
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
public class Packet2Handshake extends DefinedPacket
|
||||||
|
{
|
||||||
|
|
||||||
|
private byte procolVersion;
|
||||||
|
private String username;
|
||||||
|
private String host;
|
||||||
|
private int port;
|
||||||
|
|
||||||
|
private Packet2Handshake()
|
||||||
|
{
|
||||||
|
super( 0x02 );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(ByteBuf buf)
|
||||||
|
{
|
||||||
|
procolVersion = buf.readByte();
|
||||||
|
username = readString( buf );
|
||||||
|
host = readString( buf );
|
||||||
|
port = buf.readInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(ByteBuf buf)
|
||||||
|
{
|
||||||
|
buf.writeByte( procolVersion );
|
||||||
|
writeString( username, buf );
|
||||||
|
writeString( host, buf );
|
||||||
|
buf.writeInt( port );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(AbstractPacketHandler handler) throws Exception
|
||||||
|
{
|
||||||
|
handler.handle( this );
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,44 @@
|
|||||||
|
package net.md_5.bungee.protocol.packet;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@ToString
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
public class Packet3Chat extends DefinedPacket
|
||||||
|
{
|
||||||
|
|
||||||
|
private String message;
|
||||||
|
|
||||||
|
private Packet3Chat()
|
||||||
|
{
|
||||||
|
super( 0x03 );
|
||||||
|
}
|
||||||
|
|
||||||
|
public Packet3Chat(String message)
|
||||||
|
{
|
||||||
|
this();
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(ByteBuf buf)
|
||||||
|
{
|
||||||
|
message = readString( buf );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(ByteBuf buf)
|
||||||
|
{
|
||||||
|
writeString( message, buf );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(AbstractPacketHandler handler) throws Exception
|
||||||
|
{
|
||||||
|
handler.handle( this );
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,58 @@
|
|||||||
|
package net.md_5.bungee.protocol.packet;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
@ToString
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
public class Packet9Respawn extends DefinedPacket
|
||||||
|
{
|
||||||
|
|
||||||
|
private int dimension;
|
||||||
|
private byte difficulty;
|
||||||
|
private byte gameMode;
|
||||||
|
private short worldHeight;
|
||||||
|
private String levelType;
|
||||||
|
|
||||||
|
private Packet9Respawn()
|
||||||
|
{
|
||||||
|
super( 0x09 );
|
||||||
|
}
|
||||||
|
|
||||||
|
public Packet9Respawn(int dimension, byte difficulty, byte gameMode, short worldHeight, String levelType)
|
||||||
|
{
|
||||||
|
this();
|
||||||
|
this.dimension = dimension;
|
||||||
|
this.difficulty = difficulty;
|
||||||
|
this.gameMode = gameMode;
|
||||||
|
this.worldHeight = worldHeight;
|
||||||
|
this.levelType = levelType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(ByteBuf buf)
|
||||||
|
{
|
||||||
|
dimension = buf.readInt();
|
||||||
|
difficulty = buf.readByte();
|
||||||
|
gameMode = buf.readByte();
|
||||||
|
worldHeight = buf.readShort();
|
||||||
|
levelType = readString( buf );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(ByteBuf buf)
|
||||||
|
{
|
||||||
|
buf.writeInt( dimension );
|
||||||
|
buf.writeByte( difficulty );
|
||||||
|
buf.writeByte( gameMode );
|
||||||
|
buf.writeShort( worldHeight );
|
||||||
|
writeString( levelType, buf );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(AbstractPacketHandler handler) throws Exception
|
||||||
|
{
|
||||||
|
handler.handle( this );
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,52 @@
|
|||||||
|
package net.md_5.bungee.protocol.packet;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@ToString
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
public class PacketC9PlayerListItem extends DefinedPacket
|
||||||
|
{
|
||||||
|
|
||||||
|
private String username;
|
||||||
|
private boolean online;
|
||||||
|
private short ping;
|
||||||
|
|
||||||
|
private PacketC9PlayerListItem()
|
||||||
|
{
|
||||||
|
super( 0xC9 );
|
||||||
|
}
|
||||||
|
|
||||||
|
public PacketC9PlayerListItem(String username, boolean online, short ping)
|
||||||
|
{
|
||||||
|
super( 0xC9 );
|
||||||
|
this.username = username;
|
||||||
|
this.online = online;
|
||||||
|
this.ping = ping;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(ByteBuf buf)
|
||||||
|
{
|
||||||
|
username = readString( buf );
|
||||||
|
online = buf.readBoolean();
|
||||||
|
ping = buf.readShort();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(ByteBuf buf)
|
||||||
|
{
|
||||||
|
writeString( username, buf );
|
||||||
|
buf.writeBoolean( online );
|
||||||
|
buf.writeShort(ping );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(AbstractPacketHandler handler) throws Exception
|
||||||
|
{
|
||||||
|
handler.handle( this );
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,48 @@
|
|||||||
|
package net.md_5.bungee.protocol.packet;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
@ToString
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
public class PacketCCSettings extends DefinedPacket
|
||||||
|
{
|
||||||
|
|
||||||
|
private String locale;
|
||||||
|
private byte viewDistance;
|
||||||
|
private byte chatFlags;
|
||||||
|
private byte difficulty;
|
||||||
|
private boolean showCape;
|
||||||
|
|
||||||
|
private PacketCCSettings()
|
||||||
|
{
|
||||||
|
super( 0xCC );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(ByteBuf buf)
|
||||||
|
{
|
||||||
|
locale = readString( buf );
|
||||||
|
viewDistance = buf.readByte();
|
||||||
|
chatFlags = buf.readByte();
|
||||||
|
difficulty = buf.readByte();
|
||||||
|
showCape = buf.readBoolean();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(ByteBuf buf)
|
||||||
|
{
|
||||||
|
writeString( locale, buf );
|
||||||
|
buf.writeByte( viewDistance );
|
||||||
|
buf.writeByte( chatFlags );
|
||||||
|
buf.writeByte( difficulty );
|
||||||
|
buf.writeBoolean( showCape );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(AbstractPacketHandler handler) throws Exception
|
||||||
|
{
|
||||||
|
handler.handle( this );
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,42 @@
|
|||||||
|
package net.md_5.bungee.protocol.packet;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
@ToString
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
public class PacketCDClientStatus extends DefinedPacket
|
||||||
|
{
|
||||||
|
|
||||||
|
private byte payload;
|
||||||
|
|
||||||
|
private PacketCDClientStatus()
|
||||||
|
{
|
||||||
|
super( 0xCD );
|
||||||
|
}
|
||||||
|
|
||||||
|
public PacketCDClientStatus(byte payload)
|
||||||
|
{
|
||||||
|
this();
|
||||||
|
this.payload = payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(ByteBuf buf)
|
||||||
|
{
|
||||||
|
payload = buf.readByte();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(ByteBuf buf)
|
||||||
|
{
|
||||||
|
buf.writeByte( payload );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(AbstractPacketHandler handler) throws Exception
|
||||||
|
{
|
||||||
|
handler.handle( this );
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,55 @@
|
|||||||
|
package net.md_5.bungee.protocol.packet;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@ToString
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
public class PacketCEScoreboardObjective extends DefinedPacket
|
||||||
|
{
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
private String text;
|
||||||
|
/**
|
||||||
|
* 0 to create, 1 to remove.
|
||||||
|
*/
|
||||||
|
private byte action;
|
||||||
|
|
||||||
|
private PacketCEScoreboardObjective()
|
||||||
|
{
|
||||||
|
super( 0xCE );
|
||||||
|
}
|
||||||
|
|
||||||
|
public PacketCEScoreboardObjective(String name, String text, byte action)
|
||||||
|
{
|
||||||
|
this();
|
||||||
|
this.name = name;
|
||||||
|
this.text = text;
|
||||||
|
this.action = action;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(ByteBuf buf)
|
||||||
|
{
|
||||||
|
name = readString( buf );
|
||||||
|
text = readString( buf );
|
||||||
|
action = buf.readByte();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(ByteBuf buf)
|
||||||
|
{
|
||||||
|
writeString( name, buf );
|
||||||
|
writeString( text, buf );
|
||||||
|
buf.writeByte( action );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(AbstractPacketHandler handler) throws Exception
|
||||||
|
{
|
||||||
|
handler.handle( this );
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,56 @@
|
|||||||
|
package net.md_5.bungee.protocol.packet;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@ToString
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
public class PacketCFScoreboardScore extends DefinedPacket
|
||||||
|
{
|
||||||
|
|
||||||
|
private String itemName;
|
||||||
|
/**
|
||||||
|
* 0 = create / update, 1 = remove.
|
||||||
|
*/
|
||||||
|
private byte action;
|
||||||
|
private String scoreName;
|
||||||
|
private int value;
|
||||||
|
|
||||||
|
private PacketCFScoreboardScore()
|
||||||
|
{
|
||||||
|
super( 0xCF );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(ByteBuf buf)
|
||||||
|
{
|
||||||
|
itemName = readString( buf );
|
||||||
|
action = buf.readByte();
|
||||||
|
if ( action != 1 )
|
||||||
|
{
|
||||||
|
scoreName = readString( buf );
|
||||||
|
value = buf.readInt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(ByteBuf buf)
|
||||||
|
{
|
||||||
|
writeString( itemName, buf );
|
||||||
|
buf.writeByte( action );
|
||||||
|
if ( action != 1 )
|
||||||
|
{
|
||||||
|
writeString( scoreName, buf );
|
||||||
|
buf.writeInt( value );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(AbstractPacketHandler handler) throws Exception
|
||||||
|
{
|
||||||
|
handler.handle( this );
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,44 @@
|
|||||||
|
package net.md_5.bungee.protocol.packet;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@ToString
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
public class PacketD0DisplayScoreboard extends DefinedPacket
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 0 = list, 1 = side, 2 = below.
|
||||||
|
*/
|
||||||
|
private byte position;
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private PacketD0DisplayScoreboard()
|
||||||
|
{
|
||||||
|
super( 0xD0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(ByteBuf buf)
|
||||||
|
{
|
||||||
|
position = buf.readByte();
|
||||||
|
name = readString( buf );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(ByteBuf buf)
|
||||||
|
{
|
||||||
|
buf.writeByte( position );
|
||||||
|
writeString( name, buf );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(AbstractPacketHandler handler) throws Exception
|
||||||
|
{
|
||||||
|
handler.handle( this );
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,92 @@
|
|||||||
|
package net.md_5.bungee.protocol.packet;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@ToString
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
public class PacketD1Team extends DefinedPacket
|
||||||
|
{
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
/**
|
||||||
|
* 0 - create, 1 remove, 2 info update, 3 player add, 4 player remove.
|
||||||
|
*/
|
||||||
|
private byte mode;
|
||||||
|
private String displayName;
|
||||||
|
private String prefix;
|
||||||
|
private String suffix;
|
||||||
|
private boolean friendlyFire;
|
||||||
|
private short playerCount;
|
||||||
|
private String[] players;
|
||||||
|
|
||||||
|
private PacketD1Team()
|
||||||
|
{
|
||||||
|
super( 0xD1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Packet to destroy a team.
|
||||||
|
*
|
||||||
|
* @param name
|
||||||
|
*/
|
||||||
|
public PacketD1Team(String name)
|
||||||
|
{
|
||||||
|
this();
|
||||||
|
this.name = name;
|
||||||
|
this.mode = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(ByteBuf buf)
|
||||||
|
{
|
||||||
|
name = readString( buf );
|
||||||
|
mode = buf.readByte();
|
||||||
|
if ( mode == 0 || mode == 2 )
|
||||||
|
{
|
||||||
|
displayName = readString( buf );
|
||||||
|
prefix = readString( buf );
|
||||||
|
suffix = readString( buf );
|
||||||
|
friendlyFire = buf.readBoolean();
|
||||||
|
}
|
||||||
|
if ( mode == 0 || mode == 3 || mode == 4 )
|
||||||
|
{
|
||||||
|
players = new String[ buf.readShort() ];
|
||||||
|
for ( int i = 0; i < getPlayers().length; i++ )
|
||||||
|
{
|
||||||
|
players[i] = readString( buf );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(ByteBuf buf)
|
||||||
|
{
|
||||||
|
writeString( name, buf );
|
||||||
|
buf.writeByte( mode );
|
||||||
|
if ( mode == 0 || mode == 2 )
|
||||||
|
{
|
||||||
|
writeString( displayName, buf );
|
||||||
|
writeString( prefix, buf );
|
||||||
|
writeString( suffix, buf );
|
||||||
|
buf.writeBoolean( friendlyFire );
|
||||||
|
}
|
||||||
|
if ( mode == 0 || mode == 3 || mode == 4 )
|
||||||
|
{
|
||||||
|
buf.writeShort( players.length );
|
||||||
|
for ( int i = 0; i < players.length; i++ )
|
||||||
|
{
|
||||||
|
writeString( players[i], buf );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(AbstractPacketHandler handler) throws Exception
|
||||||
|
{
|
||||||
|
handler.handle( this );
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,48 @@
|
|||||||
|
package net.md_5.bungee.protocol.packet;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@ToString
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
public class PacketFAPluginMessage extends DefinedPacket
|
||||||
|
{
|
||||||
|
|
||||||
|
private String tag;
|
||||||
|
private byte[] data;
|
||||||
|
|
||||||
|
private PacketFAPluginMessage()
|
||||||
|
{
|
||||||
|
super( 0xFA );
|
||||||
|
}
|
||||||
|
|
||||||
|
public PacketFAPluginMessage(String tag, byte[] data)
|
||||||
|
{
|
||||||
|
this();
|
||||||
|
this.tag = tag;
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(ByteBuf buf)
|
||||||
|
{
|
||||||
|
tag = readString( buf );
|
||||||
|
data = readArray( buf );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(ByteBuf buf)
|
||||||
|
{
|
||||||
|
writeString( tag, buf );
|
||||||
|
writeArray( data, buf );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(AbstractPacketHandler handler) throws Exception
|
||||||
|
{
|
||||||
|
handler.handle( this );
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,48 @@
|
|||||||
|
package net.md_5.bungee.protocol.packet;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@ToString
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
public class PacketFCEncryptionResponse extends DefinedPacket
|
||||||
|
{
|
||||||
|
|
||||||
|
private byte[] sharedSecret;
|
||||||
|
private byte[] verifyToken;
|
||||||
|
|
||||||
|
private PacketFCEncryptionResponse()
|
||||||
|
{
|
||||||
|
super( 0xFC );
|
||||||
|
}
|
||||||
|
|
||||||
|
public PacketFCEncryptionResponse(byte[] sharedSecret, byte[] verifyToken)
|
||||||
|
{
|
||||||
|
this();
|
||||||
|
this.sharedSecret = sharedSecret;
|
||||||
|
this.verifyToken = verifyToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(ByteBuf buf)
|
||||||
|
{
|
||||||
|
sharedSecret = readArray( buf );
|
||||||
|
verifyToken = readArray( buf );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(ByteBuf buf)
|
||||||
|
{
|
||||||
|
writeArray( sharedSecret, buf );
|
||||||
|
writeArray( verifyToken, buf );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(AbstractPacketHandler handler) throws Exception
|
||||||
|
{
|
||||||
|
handler.handle( this );
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,52 @@
|
|||||||
|
package net.md_5.bungee.protocol.packet;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@ToString
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
public class PacketFDEncryptionRequest extends DefinedPacket
|
||||||
|
{
|
||||||
|
|
||||||
|
private String serverId;
|
||||||
|
private byte[] publicKey;
|
||||||
|
private byte[] verifyToken;
|
||||||
|
|
||||||
|
private PacketFDEncryptionRequest()
|
||||||
|
{
|
||||||
|
super( 0xFD );
|
||||||
|
}
|
||||||
|
|
||||||
|
public PacketFDEncryptionRequest(String serverId, byte[] publicKey, byte[] verifyToken)
|
||||||
|
{
|
||||||
|
this();
|
||||||
|
this.serverId = serverId;
|
||||||
|
this.publicKey = publicKey;
|
||||||
|
this.verifyToken = verifyToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(ByteBuf buf)
|
||||||
|
{
|
||||||
|
serverId = readString( buf );
|
||||||
|
publicKey = readArray( buf );
|
||||||
|
verifyToken = readArray( buf );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(ByteBuf buf)
|
||||||
|
{
|
||||||
|
writeString( serverId, buf );
|
||||||
|
writeArray( publicKey, buf );
|
||||||
|
writeArray( verifyToken, buf );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(AbstractPacketHandler handler) throws Exception
|
||||||
|
{
|
||||||
|
handler.handle( this );
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,36 @@
|
|||||||
|
package net.md_5.bungee.protocol.packet;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
@ToString
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
public class PacketFEPing extends DefinedPacket
|
||||||
|
{
|
||||||
|
|
||||||
|
private byte version;
|
||||||
|
|
||||||
|
private PacketFEPing()
|
||||||
|
{
|
||||||
|
super( 0xFE );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(ByteBuf buf)
|
||||||
|
{
|
||||||
|
version = buf.readByte();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(ByteBuf buf)
|
||||||
|
{
|
||||||
|
buf.writeByte( version );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(AbstractPacketHandler handler) throws Exception
|
||||||
|
{
|
||||||
|
handler.handle( this );
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,44 @@
|
|||||||
|
package net.md_5.bungee.protocol.packet;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@ToString
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
public class PacketFFKick extends DefinedPacket
|
||||||
|
{
|
||||||
|
|
||||||
|
private String message;
|
||||||
|
|
||||||
|
private PacketFFKick()
|
||||||
|
{
|
||||||
|
super( 0xFF );
|
||||||
|
}
|
||||||
|
|
||||||
|
public PacketFFKick(String message)
|
||||||
|
{
|
||||||
|
this();
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(ByteBuf buf)
|
||||||
|
{
|
||||||
|
message = readString( buf );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(ByteBuf buf)
|
||||||
|
{
|
||||||
|
writeString( message, buf );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(AbstractPacketHandler handler) throws Exception
|
||||||
|
{
|
||||||
|
handler.handle( this );
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,52 @@
|
|||||||
|
package net.md_5.bungee.protocol.packet.forge;
|
||||||
|
|
||||||
|
import net.md_5.bungee.protocol.packet.*;
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
@ToString
|
||||||
|
@EqualsAndHashCode(callSuper = false)
|
||||||
|
public class Forge1Login extends Packet1Login
|
||||||
|
{
|
||||||
|
|
||||||
|
private Forge1Login()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Forge1Login(int entityId, String levelType, byte gameMode, int dimension, byte difficulty, byte unused, byte maxPlayers)
|
||||||
|
{
|
||||||
|
super( entityId, levelType, gameMode, dimension, difficulty, unused, maxPlayers );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(ByteBuf buf)
|
||||||
|
{
|
||||||
|
entityId = buf.readInt();
|
||||||
|
levelType = readString( buf );
|
||||||
|
gameMode = buf.readByte();
|
||||||
|
dimension = buf.readInt();
|
||||||
|
difficulty = buf.readByte();
|
||||||
|
unused = buf.readByte();
|
||||||
|
maxPlayers = buf.readByte();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(ByteBuf buf)
|
||||||
|
{
|
||||||
|
buf.writeInt( entityId );
|
||||||
|
writeString( levelType, buf );
|
||||||
|
buf.writeByte( gameMode );
|
||||||
|
buf.writeInt( dimension );
|
||||||
|
buf.writeByte( difficulty );
|
||||||
|
buf.writeByte( unused );
|
||||||
|
buf.writeByte( maxPlayers );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(AbstractPacketHandler handler) throws Exception
|
||||||
|
{
|
||||||
|
handler.handle( this );
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,16 @@
|
|||||||
|
package net.md_5.bungee.protocol.skip;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
|
||||||
|
public class BulkChunk extends Instruction
|
||||||
|
{
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void read(ByteBuf in)
|
||||||
|
{
|
||||||
|
short count = in.readShort();
|
||||||
|
int size = in.readInt();
|
||||||
|
in.readBoolean();
|
||||||
|
in.skipBytes( size + count * 12 );
|
||||||
|
}
|
||||||
|
}
|
@@ -1,7 +1,6 @@
|
|||||||
package net.md_5.mendax.datainput;
|
package net.md_5.bungee.protocol.skip;
|
||||||
|
|
||||||
import java.io.DataInput;
|
import io.netty.buffer.ByteBuf;
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
class ByteHeader extends Instruction
|
class ByteHeader extends Instruction
|
||||||
{
|
{
|
||||||
@@ -14,12 +13,12 @@ class ByteHeader extends Instruction
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void read(DataInput in, byte[] buffer) throws IOException
|
void read(ByteBuf in)
|
||||||
{
|
{
|
||||||
byte size = in.readByte();
|
byte size = in.readByte();
|
||||||
for ( byte b = 0; b < size; b++ )
|
for ( byte b = 0; b < size; b++ )
|
||||||
{
|
{
|
||||||
child.read( in, buffer );
|
child.read( in );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,7 +1,6 @@
|
|||||||
package net.md_5.mendax.datainput;
|
package net.md_5.bungee.protocol.skip;
|
||||||
|
|
||||||
import java.io.DataInput;
|
import io.netty.buffer.ByteBuf;
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
abstract class Instruction
|
abstract class Instruction
|
||||||
{
|
{
|
||||||
@@ -26,11 +25,8 @@ abstract class Instruction
|
|||||||
static final Instruction USHORT_BYTE = new UnsignedShortByte();
|
static final Instruction USHORT_BYTE = new UnsignedShortByte();
|
||||||
// Illegal forward references below this line
|
// Illegal forward references below this line
|
||||||
static final Instruction BYTE_INT = new ByteHeader( INT );
|
static final Instruction BYTE_INT = new ByteHeader( INT );
|
||||||
|
// Custom instructions
|
||||||
|
static final Instruction STRING_ARRAY = new ShortHeader( STRING );
|
||||||
|
|
||||||
abstract void read(DataInput in, byte[] buffer) throws IOException;
|
abstract void read(ByteBuf in);
|
||||||
|
|
||||||
final void skip(DataInput in, byte[] buffer, int len) throws IOException
|
|
||||||
{
|
|
||||||
in.readFully( buffer, 0, len );
|
|
||||||
}
|
|
||||||
}
|
}
|
@@ -1,7 +1,6 @@
|
|||||||
package net.md_5.mendax.datainput;
|
package net.md_5.bungee.protocol.skip;
|
||||||
|
|
||||||
import java.io.DataInput;
|
import io.netty.buffer.ByteBuf;
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
class IntHeader extends Instruction
|
class IntHeader extends Instruction
|
||||||
{
|
{
|
||||||
@@ -14,12 +13,12 @@ class IntHeader extends Instruction
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void read(DataInput in, byte[] buffer) throws IOException
|
void read(ByteBuf in)
|
||||||
{
|
{
|
||||||
int size = in.readInt();
|
int size = in.readInt();
|
||||||
for ( int i = 0; i < size; i++ )
|
for ( int i = 0; i < size; i++ )
|
||||||
{
|
{
|
||||||
child.read( in, buffer );
|
child.read( in );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -0,0 +1,18 @@
|
|||||||
|
package net.md_5.bungee.protocol.skip;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
|
||||||
|
class Item extends Instruction
|
||||||
|
{
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void read(ByteBuf in)
|
||||||
|
{
|
||||||
|
short type = in.readShort();
|
||||||
|
if ( type >= 0 )
|
||||||
|
{
|
||||||
|
in.skipBytes( 3 );
|
||||||
|
SHORT_BYTE.read( in );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -1,7 +1,6 @@
|
|||||||
package net.md_5.mendax.datainput;
|
package net.md_5.bungee.protocol.skip;
|
||||||
|
|
||||||
import java.io.DataInput;
|
import io.netty.buffer.ByteBuf;
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
class Jump extends Instruction
|
class Jump extends Instruction
|
||||||
{
|
{
|
||||||
@@ -18,8 +17,8 @@ class Jump extends Instruction
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void read(DataInput in, byte[] buffer) throws IOException
|
void read(ByteBuf in)
|
||||||
{
|
{
|
||||||
skip( in, buffer, len );
|
in.skipBytes( len );
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,13 +1,12 @@
|
|||||||
package net.md_5.mendax.datainput;
|
package net.md_5.bungee.protocol.skip;
|
||||||
|
|
||||||
import java.io.DataInput;
|
import io.netty.buffer.ByteBuf;
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
class MetaData extends Instruction
|
class MetaData extends Instruction
|
||||||
{
|
{
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void read(DataInput in, byte[] buffer) throws IOException
|
void read(ByteBuf in)
|
||||||
{
|
{
|
||||||
int x = in.readUnsignedByte();
|
int x = in.readUnsignedByte();
|
||||||
while ( x != 127 )
|
while ( x != 127 )
|
||||||
@@ -16,25 +15,25 @@ class MetaData extends Instruction
|
|||||||
switch ( type )
|
switch ( type )
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
BYTE.read( in, buffer );
|
BYTE.read( in );
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
SHORT.read( in, buffer );
|
SHORT.read( in );
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
INT.read( in, buffer );
|
INT.read( in );
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
FLOAT.read( in, buffer );
|
FLOAT.read( in );
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
STRING.read( in, buffer );
|
STRING.read( in );
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
ITEM.read( in, buffer );
|
ITEM.read( in );
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
skip( in, buffer, 12 ); // int, int, int
|
in.skipBytes( 12 ); // int, int, int
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException( "Unknown metadata type " + type );
|
throw new IllegalArgumentException( "Unknown metadata type " + type );
|
@@ -0,0 +1,17 @@
|
|||||||
|
package net.md_5.bungee.protocol.skip;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
|
||||||
|
class OptionalMotion extends Instruction
|
||||||
|
{
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void read(ByteBuf in)
|
||||||
|
{
|
||||||
|
int data = in.readInt();
|
||||||
|
if ( data > 0 )
|
||||||
|
{
|
||||||
|
in.skipBytes( 6 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -1,24 +1,24 @@
|
|||||||
package net.md_5.mendax.datainput;
|
package net.md_5.bungee.protocol.skip;
|
||||||
|
|
||||||
import java.io.DataInput;
|
import io.netty.buffer.ByteBuf;
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import net.md_5.mendax.PacketDefinitions;
|
import net.md_5.bungee.protocol.OpCode;
|
||||||
import net.md_5.mendax.PacketDefinitions.OpCode;
|
import net.md_5.bungee.protocol.Protocol;
|
||||||
|
|
||||||
public class DataInputPacketReader
|
public class PacketReader
|
||||||
{
|
{
|
||||||
|
|
||||||
private static final Instruction[][] instructions = new Instruction[ 256 ][];
|
private final Instruction[][] instructions;
|
||||||
|
|
||||||
static
|
public PacketReader(Protocol protocol)
|
||||||
{
|
{
|
||||||
|
instructions = new Instruction[ protocol.getOpCodes().length ][];
|
||||||
for ( int i = 0; i < instructions.length; i++ )
|
for ( int i = 0; i < instructions.length; i++ )
|
||||||
{
|
{
|
||||||
List<Instruction> output = new ArrayList<>();
|
List<Instruction> output = new ArrayList<>();
|
||||||
|
|
||||||
OpCode[] enums = PacketDefinitions.opCodes[i];
|
OpCode[] enums = protocol.getOpCodes()[i];
|
||||||
if ( enums != null )
|
if ( enums != null )
|
||||||
{
|
{
|
||||||
for ( OpCode struct : enums )
|
for ( OpCode struct : enums )
|
||||||
@@ -59,35 +59,16 @@ public class DataInputPacketReader
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void readPacket(int packetId, DataInput in, byte[] buffer, int protocol) throws IOException
|
public void tryRead(short packetId, ByteBuf in)
|
||||||
{
|
{
|
||||||
Instruction[] packetDef = null;
|
Instruction[] packetDef = instructions[packetId];
|
||||||
if ( packetId + protocol < instructions.length )
|
|
||||||
{
|
|
||||||
packetDef = instructions[packetId + protocol];
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( packetDef == null )
|
if ( packetDef != null )
|
||||||
{
|
{
|
||||||
if ( protocol == PacketDefinitions.VANILLA_PROTOCOL )
|
|
||||||
{
|
|
||||||
throw new IOException( "Unknown packet id " + packetId );
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
readPacket( packetId, in, buffer, PacketDefinitions.VANILLA_PROTOCOL );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for ( Instruction instruction : packetDef )
|
for ( Instruction instruction : packetDef )
|
||||||
{
|
{
|
||||||
instruction.read( in, buffer );
|
instruction.read( in );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void readPacket(DataInput in, byte[] buffer, int protocol) throws IOException
|
|
||||||
{
|
|
||||||
int packetId = in.readUnsignedByte();
|
|
||||||
readPacket( packetId, in, buffer, protocol );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,7 +1,6 @@
|
|||||||
package net.md_5.mendax.datainput;
|
package net.md_5.bungee.protocol.skip;
|
||||||
|
|
||||||
import java.io.DataInput;
|
import io.netty.buffer.ByteBuf;
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
class ShortHeader extends Instruction
|
class ShortHeader extends Instruction
|
||||||
{
|
{
|
||||||
@@ -14,12 +13,12 @@ class ShortHeader extends Instruction
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void read(DataInput in, byte[] buffer) throws IOException
|
void read(ByteBuf in)
|
||||||
{
|
{
|
||||||
short size = in.readShort();
|
short size = in.readShort();
|
||||||
for ( short s = 0; s < size; s++ )
|
for ( short s = 0; s < size; s++ )
|
||||||
{
|
{
|
||||||
child.read( in, buffer );
|
child.read( in );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -0,0 +1,14 @@
|
|||||||
|
package net.md_5.bungee.protocol.skip;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
|
||||||
|
class UnsignedShortByte extends Instruction
|
||||||
|
{
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void read(ByteBuf in)
|
||||||
|
{
|
||||||
|
int size = in.readUnsignedShort();
|
||||||
|
in.skipBytes( size );
|
||||||
|
}
|
||||||
|
}
|
@@ -1,17 +0,0 @@
|
|||||||
package net.md_5.mendax.datainput;
|
|
||||||
|
|
||||||
import java.io.DataInput;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
public class BulkChunk extends Instruction
|
|
||||||
{
|
|
||||||
|
|
||||||
@Override
|
|
||||||
void read(DataInput in, byte[] buffer) throws IOException
|
|
||||||
{
|
|
||||||
short count = in.readShort();
|
|
||||||
int size = in.readInt();
|
|
||||||
in.readBoolean();
|
|
||||||
skip( in, buffer, size + count * 12 );
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,19 +0,0 @@
|
|||||||
package net.md_5.mendax.datainput;
|
|
||||||
|
|
||||||
import java.io.DataInput;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
class Item extends Instruction
|
|
||||||
{
|
|
||||||
|
|
||||||
@Override
|
|
||||||
void read(DataInput in, byte[] buffer) throws IOException
|
|
||||||
{
|
|
||||||
short type = in.readShort();
|
|
||||||
if ( type >= 0 )
|
|
||||||
{
|
|
||||||
skip( in, buffer, 3 );
|
|
||||||
SHORT_BYTE.read( in, buffer );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,18 +0,0 @@
|
|||||||
package net.md_5.mendax.datainput;
|
|
||||||
|
|
||||||
import java.io.DataInput;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
public class OptionalMotion extends Instruction
|
|
||||||
{
|
|
||||||
|
|
||||||
@Override
|
|
||||||
void read(DataInput in, byte[] buffer) throws IOException
|
|
||||||
{
|
|
||||||
int data = in.readInt();
|
|
||||||
if ( data > 0 )
|
|
||||||
{
|
|
||||||
skip( in, buffer, 6 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,15 +0,0 @@
|
|||||||
package net.md_5.mendax.datainput;
|
|
||||||
|
|
||||||
import java.io.DataInput;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
public class UnsignedShortByte extends Instruction
|
|
||||||
{
|
|
||||||
|
|
||||||
@Override
|
|
||||||
void read(DataInput in, byte[] buffer) throws IOException
|
|
||||||
{
|
|
||||||
int size = in.readUnsignedShort();
|
|
||||||
skip( in, buffer, size );
|
|
||||||
}
|
|
||||||
}
|
|
@@ -0,0 +1,45 @@
|
|||||||
|
package net.md_5.bungee.protocol;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
import net.md_5.bungee.protocol.packet.AbstractPacketHandler;
|
||||||
|
import net.md_5.bungee.protocol.packet.DefinedPacket;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class PacketTest
|
||||||
|
{
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPackets() throws Exception
|
||||||
|
{
|
||||||
|
AbstractPacketHandler handler = new AbstractPacketHandler()
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
for ( short i = 0; i < 256; i++ )
|
||||||
|
{
|
||||||
|
Class<? extends DefinedPacket> clazz = Vanilla.getInstance().getClasses()[ i];
|
||||||
|
if ( clazz != null )
|
||||||
|
{
|
||||||
|
Assert.assertTrue( "Packet " + clazz + " is not public", Modifier.isPublic( clazz.getModifiers() ) );
|
||||||
|
DefinedPacket packet = Vanilla.packet( i, Vanilla.getInstance() );
|
||||||
|
Assert.assertTrue( "Could not create packet with id " + i + " and class " + clazz, packet != null );
|
||||||
|
Assert.assertTrue( "Packet with id " + i + " does not have correct class (expected " + clazz + " but got " + packet.getClass(), packet.getClass() == clazz );
|
||||||
|
Assert.assertTrue( "Packet " + clazz + " does not report correct id", packet.getId() == i );
|
||||||
|
Assert.assertTrue( "Packet " + clazz + " does not have custom hash code", packet.hashCode() != System.identityHashCode( packet ) );
|
||||||
|
Assert.assertTrue( "Packet " + clazz + " does not have custom toString", packet.toString().indexOf( '@' ) == -1 );
|
||||||
|
// TODO: Enable this test again in v2
|
||||||
|
// Assert.assertTrue( "Packet " + clazz + " does not have private no args constructor", Modifier.isPrivate( clazz.getDeclaredConstructor().getModifiers() ) );
|
||||||
|
|
||||||
|
for ( Field field : clazz.getDeclaredFields() )
|
||||||
|
{
|
||||||
|
// TODO: Enable this test again in v2
|
||||||
|
// Assert.assertTrue( "Packet " + clazz + " has non private field " + field, Modifier.isPrivate( field.getModifiers() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
packet.handle( handler ); // Make sure there are no exceptions
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,14 @@
|
|||||||
|
package net.md_5.bungee.protocol;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class ProtocolTest
|
||||||
|
{
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testProtocol()
|
||||||
|
{
|
||||||
|
Assert.assertFalse( "Protocols should have different login packet", Vanilla.getInstance().getClasses()[0x01] == Forge.getInstance().classes[0x01] );
|
||||||
|
}
|
||||||
|
}
|
31
proxy/nb-configuration.xml
Normal file
31
proxy/nb-configuration.xml
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project-shared-configuration>
|
||||||
|
<!--
|
||||||
|
This file contains additional configuration written by modules in the NetBeans IDE.
|
||||||
|
The configuration is intended to be shared among all the users of project and
|
||||||
|
therefore it is assumed to be part of version control checkout.
|
||||||
|
Without this configuration present, some functionality in the IDE may be limited or fail altogether.
|
||||||
|
-->
|
||||||
|
<properties xmlns="http://www.netbeans.org/ns/maven-properties-data/1">
|
||||||
|
<!--
|
||||||
|
Properties that influence various parts of the IDE, especially code formatting and the like.
|
||||||
|
You can copy and paste the single properties, into the pom.xml file and the IDE will pick them up.
|
||||||
|
That way multiple projects can share the same settings (useful for formatting rules for example).
|
||||||
|
Any value defined here will override the pom.xml file value but is only applicable to the current project.
|
||||||
|
-->
|
||||||
|
<org-netbeans-modules-editor-indent.CodeStyle.usedProfile>project</org-netbeans-modules-editor-indent.CodeStyle.usedProfile>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.classDeclBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.classDeclBracePlacement>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.otherBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.otherBracePlacement>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.methodDeclBracePlacement>NEW_LINE</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.methodDeclBracePlacement>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinMethodCallParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinMethodCallParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSwitchParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSwitchParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinCatchParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinCatchParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinTryParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinTryParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSynchronizedParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinSynchronizedParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinArrayInitBrackets>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinArrayInitBrackets>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinWhileParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinWhileParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinIfParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinIfParens>
|
||||||
|
<org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinForParens>true</org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.spaceWithinForParens>
|
||||||
|
</properties>
|
||||||
|
</project-shared-configuration>
|
@@ -6,39 +6,86 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>net.md-5</groupId>
|
<groupId>net.md-5</groupId>
|
||||||
<artifactId>bungeecord-parent</artifactId>
|
<artifactId>bungeecord-parent</artifactId>
|
||||||
<version>1.4.7-SNAPSHOT</version>
|
<version>1.5-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<groupId>net.md-5</groupId>
|
<groupId>net.md-5</groupId>
|
||||||
<artifactId>bungeecord-proxy</artifactId>
|
<artifactId>bungeecord-proxy</artifactId>
|
||||||
<version>1.4.7-SNAPSHOT</version>
|
<version>1.5-SNAPSHOT</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>BungeeCord-Proxy</name>
|
<name>BungeeCord-Proxy</name>
|
||||||
<description>Proxy component of the Elastic Portal Suite</description>
|
<description>Proxy component of the Elastic Portal Suite</description>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.netty</groupId>
|
||||||
|
<artifactId>netty-codec</artifactId>
|
||||||
|
<version>${netty.version}</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.netty</groupId>
|
||||||
|
<artifactId>netty-handler</artifactId>
|
||||||
|
<version>${netty.version}</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>jline</groupId>
|
||||||
|
<artifactId>jline</artifactId>
|
||||||
|
<version>2.11</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.md-5</groupId>
|
<groupId>net.md-5</groupId>
|
||||||
<artifactId>bungeecord-protocol</artifactId>
|
<artifactId>bungeecord-protocol</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.md-5</groupId>
|
<groupId>net.md-5</groupId>
|
||||||
<artifactId>bungeecord-api</artifactId>
|
<artifactId>bungeecord-api</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.sf.trove4j</groupId>
|
||||||
|
<artifactId>trove4j</artifactId>
|
||||||
|
<version>3.0.3</version>
|
||||||
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>mysql</groupId>
|
<groupId>mysql</groupId>
|
||||||
<artifactId>mysql-connector-java</artifactId>
|
<artifactId>mysql-connector-java</artifactId>
|
||||||
<version>5.1.22</version>
|
<version>5.1.24</version>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.javassist</groupId>
|
||||||
|
<artifactId>javassist</artifactId>
|
||||||
|
<version>3.18.0-GA</version>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.xerial</groupId>
|
||||||
|
<artifactId>sqlite-jdbc</artifactId>
|
||||||
|
<version>3.7.2</version>
|
||||||
|
<scope>runtime</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<finalName>BungeeCord</finalName>
|
<finalName>BungeeCord</finalName>
|
||||||
<plugins>
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<!-- Don't deploy proxy to maven repo, only APIs -->
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-deploy-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<skip>true</skip>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-jar-plugin</artifactId>
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
@@ -75,7 +122,6 @@
|
|||||||
</excludes>
|
</excludes>
|
||||||
</filter>
|
</filter>
|
||||||
</filters>
|
</filters>
|
||||||
<finalName>${project.build.finalName}-shaded</finalName>
|
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
|
@@ -1,43 +1,72 @@
|
|||||||
package net.md_5.bungee;
|
package net.md_5.bungee;
|
||||||
|
|
||||||
|
import com.google.common.io.ByteStreams;
|
||||||
|
import net.md_5.bungee.log.BungeeLogger;
|
||||||
|
import net.md_5.bungee.reconnect.SQLReconnectHandler;
|
||||||
|
import net.md_5.bungee.scheduler.BungeeScheduler;
|
||||||
|
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||||
|
import com.ning.http.client.AsyncHttpClient;
|
||||||
|
import com.ning.http.client.AsyncHttpClientConfig;
|
||||||
|
import com.ning.http.client.providers.netty.NettyAsyncHttpProvider;
|
||||||
|
import com.ning.http.client.providers.netty.NettyAsyncHttpProviderConfig;
|
||||||
|
import io.netty.bootstrap.ServerBootstrap;
|
||||||
|
import io.netty.channel.Channel;
|
||||||
|
import io.netty.channel.ChannelException;
|
||||||
|
import io.netty.channel.ChannelFuture;
|
||||||
|
import io.netty.channel.ChannelFutureListener;
|
||||||
|
import io.netty.channel.MultithreadEventLoopGroup;
|
||||||
|
import io.netty.channel.nio.NioEventLoopGroup;
|
||||||
|
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||||
import net.md_5.bungee.config.Configuration;
|
import net.md_5.bungee.config.Configuration;
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.io.PrintStream;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.Socket;
|
import java.util.Calendar;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.MissingResourceException;
|
||||||
|
import java.util.ResourceBundle;
|
||||||
import java.util.Timer;
|
import java.util.Timer;
|
||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.locks.ReadWriteLock;
|
||||||
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
import jline.UnsupportedTerminal;
|
||||||
|
import jline.console.ConsoleReader;
|
||||||
|
import jline.internal.Log;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import lombok.Synchronized;
|
import lombok.Synchronized;
|
||||||
import static net.md_5.bungee.Logger.$;
|
import net.md_5.bungee.api.ChatColor;
|
||||||
|
import net.md_5.bungee.api.CommandSender;
|
||||||
import net.md_5.bungee.api.ProxyServer;
|
import net.md_5.bungee.api.ProxyServer;
|
||||||
import net.md_5.bungee.api.ReconnectHandler;
|
import net.md_5.bungee.api.ReconnectHandler;
|
||||||
import net.md_5.bungee.api.TabListHandler;
|
|
||||||
import net.md_5.bungee.api.config.ConfigurationAdapter;
|
import net.md_5.bungee.api.config.ConfigurationAdapter;
|
||||||
import net.md_5.bungee.api.config.ListenerInfo;
|
import net.md_5.bungee.api.config.ListenerInfo;
|
||||||
import net.md_5.bungee.api.config.ServerInfo;
|
import net.md_5.bungee.api.config.ServerInfo;
|
||||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||||
import net.md_5.bungee.api.connection.Server;
|
|
||||||
import net.md_5.bungee.api.plugin.Plugin;
|
import net.md_5.bungee.api.plugin.Plugin;
|
||||||
import net.md_5.bungee.api.plugin.PluginManager;
|
import net.md_5.bungee.api.plugin.PluginManager;
|
||||||
|
import net.md_5.bungee.api.scheduler.TaskScheduler;
|
||||||
|
import net.md_5.bungee.api.tab.CustomTabList;
|
||||||
import net.md_5.bungee.command.*;
|
import net.md_5.bungee.command.*;
|
||||||
import net.md_5.bungee.config.YamlConfig;
|
import net.md_5.bungee.config.YamlConfig;
|
||||||
import net.md_5.bungee.packet.DefinedPacket;
|
import net.md_5.bungee.log.LoggingOutputStream;
|
||||||
import net.md_5.bungee.packet.PacketFAPluginMessage;
|
import net.md_5.bungee.netty.PipelineUtils;
|
||||||
|
import net.md_5.bungee.protocol.packet.DefinedPacket;
|
||||||
|
import net.md_5.bungee.protocol.packet.Packet3Chat;
|
||||||
|
import net.md_5.bungee.protocol.packet.PacketFAPluginMessage;
|
||||||
|
import net.md_5.bungee.protocol.Vanilla;
|
||||||
|
import net.md_5.bungee.scheduler.BungeeThreadPool;
|
||||||
|
import net.md_5.bungee.tab.Custom;
|
||||||
|
import net.md_5.bungee.util.CaseInsensitiveMap;
|
||||||
|
import org.fusesource.jansi.AnsiConsole;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main BungeeCord proxy class.
|
* Main BungeeCord proxy class.
|
||||||
@@ -45,14 +74,6 @@ import net.md_5.bungee.packet.PacketFAPluginMessage;
|
|||||||
public class BungeeCord extends ProxyServer
|
public class BungeeCord extends ProxyServer
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
|
||||||
* Server protocol version.
|
|
||||||
*/
|
|
||||||
public static final byte PROTOCOL_VERSION = 51;
|
|
||||||
/**
|
|
||||||
* Server game version.
|
|
||||||
*/
|
|
||||||
public static final String GAME_VERSION = "1.4.6";
|
|
||||||
/**
|
/**
|
||||||
* Current operation state.
|
* Current operation state.
|
||||||
*/
|
*/
|
||||||
@@ -62,32 +83,33 @@ public class BungeeCord extends ProxyServer
|
|||||||
*/
|
*/
|
||||||
public final Configuration config = new Configuration();
|
public final Configuration config = new Configuration();
|
||||||
/**
|
/**
|
||||||
* Thread pool.
|
* Localization bundle.
|
||||||
*/
|
*/
|
||||||
public final ExecutorService threadPool = Executors.newCachedThreadPool();
|
public final ResourceBundle bundle = ResourceBundle.getBundle( "messages_en" );
|
||||||
|
/**
|
||||||
|
* Thread pools.
|
||||||
|
*/
|
||||||
|
public final ScheduledThreadPoolExecutor executors = new BungeeThreadPool( new ThreadFactoryBuilder().setNameFormat( "Bungee Pool Thread #%1$d" ).build() );
|
||||||
|
public final MultithreadEventLoopGroup eventLoops = new NioEventLoopGroup( Runtime.getRuntime().availableProcessors(), new ThreadFactoryBuilder().setNameFormat( "Netty IO Thread #%1$d" ).build() );
|
||||||
/**
|
/**
|
||||||
* locations.yml save thread.
|
* locations.yml save thread.
|
||||||
*/
|
*/
|
||||||
private final Timer saveThread = new Timer( "Reconnect Saver" );
|
private final Timer saveThread = new Timer( "Reconnect Saver" );
|
||||||
|
private final Timer metricsThread = new Timer( "Metrics Thread" );
|
||||||
/**
|
/**
|
||||||
* Server socket listener.
|
* Server socket listener.
|
||||||
*/
|
*/
|
||||||
private Collection<ListenThread> listeners = new HashSet<>();
|
private Collection<Channel> listeners = new HashSet<>();
|
||||||
/**
|
/**
|
||||||
* Fully qualified connections.
|
* Fully qualified connections.
|
||||||
*/
|
*/
|
||||||
public Map<String, UserConnection> connections = new ConcurrentHashMap<>();
|
private final Map<String, UserConnection> connections = new CaseInsensitiveMap<>();
|
||||||
/**
|
private final ReadWriteLock connectionLock = new ReentrantReadWriteLock();
|
||||||
* Tab list handler
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
public TabListHandler tabListHandler;
|
|
||||||
/**
|
/**
|
||||||
* Plugin manager.
|
* Plugin manager.
|
||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
public final PluginManager pluginManager = new PluginManager();
|
public final PluginManager pluginManager = new PluginManager( this );
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
private ReconnectHandler reconnectHandler;
|
private ReconnectHandler reconnectHandler;
|
||||||
@@ -95,17 +117,33 @@ public class BungeeCord extends ProxyServer
|
|||||||
@Setter
|
@Setter
|
||||||
private ConfigurationAdapter configurationAdapter = new YamlConfig();
|
private ConfigurationAdapter configurationAdapter = new YamlConfig();
|
||||||
private final Collection<String> pluginChannels = new HashSet<>();
|
private final Collection<String> pluginChannels = new HashSet<>();
|
||||||
|
@Getter
|
||||||
|
private final File pluginsFolder = new File( "plugins" );
|
||||||
|
@Getter
|
||||||
|
private final TaskScheduler scheduler = new BungeeScheduler();
|
||||||
|
@Getter
|
||||||
|
private final AsyncHttpClient httpClient = new AsyncHttpClient(
|
||||||
|
new NettyAsyncHttpProvider(
|
||||||
|
new AsyncHttpClientConfig.Builder().setAsyncHttpClientProviderConfig(
|
||||||
|
new NettyAsyncHttpProviderConfig().addProperty( NettyAsyncHttpProviderConfig.BOSS_EXECUTOR_SERVICE, executors ) ).setExecutorService( executors ).build() ) );
|
||||||
|
@Getter
|
||||||
|
private ConsoleReader consoleReader;
|
||||||
|
@Getter
|
||||||
|
private final Logger logger;
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
getPluginManager().registerCommand( new CommandReload() );
|
// TODO: Proper fallback when we interface the manager
|
||||||
getPluginManager().registerCommand( new CommandEnd() );
|
getPluginManager().registerCommand( null, new CommandReload() );
|
||||||
getPluginManager().registerCommand( new CommandList() );
|
getPluginManager().registerCommand( null, new CommandEnd() );
|
||||||
getPluginManager().registerCommand( new CommandServer() );
|
getPluginManager().registerCommand( null, new CommandList() );
|
||||||
getPluginManager().registerCommand( new CommandIP() );
|
getPluginManager().registerCommand( null, new CommandServer() );
|
||||||
getPluginManager().registerCommand( new CommandAlert() );
|
getPluginManager().registerCommand( null, new CommandIP() );
|
||||||
getPluginManager().registerCommand( new CommandBungee() );
|
getPluginManager().registerCommand( null, new CommandAlert() );
|
||||||
getPluginManager().registerCommand( new CommandPerms() );
|
getPluginManager().registerCommand( null, new CommandBungee() );
|
||||||
|
getPluginManager().registerCommand( null, new CommandPerms() );
|
||||||
|
getPluginManager().registerCommand( null, new CommandSend() );
|
||||||
|
getPluginManager().registerCommand( null, new CommandFind() );
|
||||||
|
|
||||||
registerChannel( "BungeeCord" );
|
registerChannel( "BungeeCord" );
|
||||||
}
|
}
|
||||||
@@ -115,29 +153,55 @@ public class BungeeCord extends ProxyServer
|
|||||||
return (BungeeCord) ProxyServer.getInstance();
|
return (BungeeCord) ProxyServer.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BungeeCord() throws IOException
|
||||||
|
{
|
||||||
|
Log.setOutput( new PrintStream( ByteStreams.nullOutputStream() ) ); // TODO: Bug JLine
|
||||||
|
AnsiConsole.systemInstall();
|
||||||
|
consoleReader = new ConsoleReader();
|
||||||
|
|
||||||
|
logger = new BungeeLogger( this );
|
||||||
|
System.setErr( new PrintStream( new LoggingOutputStream( logger, Level.SEVERE ), true ) );
|
||||||
|
System.setOut( new PrintStream( new LoggingOutputStream( logger, Level.INFO ), true ) );
|
||||||
|
|
||||||
|
if ( consoleReader.getTerminal() instanceof UnsupportedTerminal )
|
||||||
|
{
|
||||||
|
logger.info( "Unable to initialize fancy terminal. To fix this on Windows, install the correct Microsoft Visual C++ 2008 Runtime" );
|
||||||
|
logger.info( "NOTE: This error is non crucial, and BungeeCord will still function correctly! Do not bug the author about it unless you are still unable to get it working" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts a new instance of BungeeCord.
|
* Starts a new instance of BungeeCord.
|
||||||
*
|
*
|
||||||
* @param args command line arguments, currently none are used
|
* @param args command line arguments, currently none are used
|
||||||
* @throws IOException when the server cannot be started
|
* @throws Exception when the server cannot be started
|
||||||
*/
|
*/
|
||||||
public static void main(String[] args) throws IOException
|
public static void main(String[] args) throws Exception
|
||||||
{
|
{
|
||||||
|
Calendar deadline = Calendar.getInstance();
|
||||||
|
deadline.set( 2013, 7, 1 ); // year, month, date
|
||||||
|
if ( Calendar.getInstance().after( deadline ) )
|
||||||
|
{
|
||||||
|
System.err.println( "*** Warning, this build is outdated ***" );
|
||||||
|
System.err.println( "*** Please download a new build from http://ci.md-5.net/job/BungeeCord ***" );
|
||||||
|
System.err.println( "*** You will get NO support regarding this build ***" );
|
||||||
|
System.err.println( "*** Server will start in 15 seconds ***" );
|
||||||
|
Thread.sleep( TimeUnit.SECONDS.toMillis( 15 ) );
|
||||||
|
}
|
||||||
|
|
||||||
BungeeCord bungee = new BungeeCord();
|
BungeeCord bungee = new BungeeCord();
|
||||||
ProxyServer.setInstance( bungee );
|
ProxyServer.setInstance( bungee );
|
||||||
$().info( "Enabled BungeeCord version " + bungee.getVersion() );
|
bungee.getLogger().info( "Enabled BungeeCord version " + bungee.getVersion() );
|
||||||
bungee.start();
|
bungee.start();
|
||||||
|
|
||||||
BufferedReader br = new BufferedReader( new InputStreamReader( System.in ) );
|
|
||||||
while ( bungee.isRunning )
|
while ( bungee.isRunning )
|
||||||
{
|
{
|
||||||
String line = br.readLine();
|
String line = bungee.getConsoleReader().readLine( ">" );
|
||||||
if ( line != null )
|
if ( line != null )
|
||||||
{
|
{
|
||||||
boolean handled = getInstance().getPluginManager().dispatchCommand( ConsoleCommandSender.getInstance(), line );
|
if ( !bungee.getPluginManager().dispatchCommand( ConsoleCommandSender.getInstance(), line ) )
|
||||||
if ( !handled )
|
|
||||||
{
|
{
|
||||||
System.err.println( "Command not found" );
|
bungee.getConsole().sendMessage( ChatColor.RED + "Command not found" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -147,21 +211,21 @@ public class BungeeCord extends ProxyServer
|
|||||||
* Start this proxy instance by loading the configuration, plugins and
|
* Start this proxy instance by loading the configuration, plugins and
|
||||||
* starting the connect thread.
|
* starting the connect thread.
|
||||||
*
|
*
|
||||||
* @throws IOException
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public void start() throws IOException
|
@Override
|
||||||
|
public void start() throws Exception
|
||||||
{
|
{
|
||||||
File plugins = new File( "plugins" );
|
pluginsFolder.mkdir();
|
||||||
plugins.mkdir();
|
pluginManager.detectPlugins( pluginsFolder );
|
||||||
pluginManager.loadPlugins( plugins );
|
|
||||||
config.load();
|
config.load();
|
||||||
if ( reconnectHandler == null )
|
if ( reconnectHandler == null )
|
||||||
{
|
{
|
||||||
reconnectHandler = new YamlReconnectHandler();
|
reconnectHandler = new SQLReconnectHandler();
|
||||||
}
|
}
|
||||||
isRunning = true;
|
isRunning = true;
|
||||||
|
|
||||||
pluginManager.enablePlugins();
|
pluginManager.loadAndEnablePlugins();
|
||||||
|
|
||||||
startListeners();
|
startListeners();
|
||||||
|
|
||||||
@@ -173,40 +237,49 @@ public class BungeeCord extends ProxyServer
|
|||||||
getReconnectHandler().save();
|
getReconnectHandler().save();
|
||||||
}
|
}
|
||||||
}, 0, TimeUnit.MINUTES.toMillis( 5 ) );
|
}, 0, TimeUnit.MINUTES.toMillis( 5 ) );
|
||||||
|
metricsThread.scheduleAtFixedRate( new Metrics(), 0, TimeUnit.MINUTES.toMillis( Metrics.PING_INTERVAL ) );
|
||||||
new Metrics().start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startListeners()
|
public void startListeners()
|
||||||
{
|
{
|
||||||
for ( ListenerInfo info : config.getListeners() )
|
for ( final ListenerInfo info : config.getListeners() )
|
||||||
{
|
{
|
||||||
try
|
ChannelFutureListener listener = new ChannelFutureListener()
|
||||||
{
|
{
|
||||||
ListenThread listener = new ListenThread( info );
|
@Override
|
||||||
listener.start();
|
public void operationComplete(ChannelFuture future) throws Exception
|
||||||
listeners.add( listener );
|
|
||||||
$().info( "Listening on " + info.getHost() );
|
|
||||||
} catch ( IOException ex )
|
|
||||||
{
|
{
|
||||||
$().log( Level.SEVERE, "Could not start listener " + info, ex );
|
if ( future.isSuccess() )
|
||||||
|
{
|
||||||
|
listeners.add( future.channel() );
|
||||||
|
getLogger().info( "Listening on " + info.getHost() );
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
getLogger().log( Level.WARNING, "Could not bind to host " + info.getHost(), future.cause() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
new ServerBootstrap()
|
||||||
|
.channel( NioServerSocketChannel.class )
|
||||||
|
.childAttr( PipelineUtils.LISTENER, info )
|
||||||
|
.childHandler( PipelineUtils.SERVER_CHILD )
|
||||||
|
.group( eventLoops )
|
||||||
|
.localAddress( info.getHost() )
|
||||||
|
.bind().addListener( listener );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stopListeners()
|
public void stopListeners()
|
||||||
{
|
{
|
||||||
for ( ListenThread listener : listeners )
|
for ( Channel listener : listeners )
|
||||||
{
|
{
|
||||||
$().log( Level.INFO, "Closing listen thread {0}", listener.socket );
|
getLogger().log( Level.INFO, "Closing listener {0}", listener );
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
listener.interrupt();
|
listener.close().syncUninterruptibly();
|
||||||
listener.socket.close();
|
} catch ( ChannelException ex )
|
||||||
listener.join();
|
|
||||||
} catch ( InterruptedException | IOException ex )
|
|
||||||
{
|
{
|
||||||
$().severe( "Could not close listen thread" );
|
getLogger().severe( "Could not close listen thread" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
listeners.clear();
|
listeners.clear();
|
||||||
@@ -215,44 +288,59 @@ public class BungeeCord extends ProxyServer
|
|||||||
@Override
|
@Override
|
||||||
public void stop()
|
public void stop()
|
||||||
{
|
{
|
||||||
this.isRunning = false;
|
new Thread( "Shutdown Thread" )
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
BungeeCord.this.isRunning = false;
|
||||||
|
|
||||||
|
httpClient.close();
|
||||||
|
executors.shutdown();
|
||||||
|
|
||||||
stopListeners();
|
stopListeners();
|
||||||
$().info( "Closing pending connections" );
|
getLogger().info( "Closing pending connections" );
|
||||||
threadPool.shutdown();
|
|
||||||
|
|
||||||
$().info( "Disconnecting " + connections.size() + " connections" );
|
connectionLock.readLock().lock();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
getLogger().info( "Disconnecting " + connections.size() + " connections" );
|
||||||
for ( UserConnection user : connections.values() )
|
for ( UserConnection user : connections.values() )
|
||||||
{
|
{
|
||||||
user.disconnect( "Proxy restarting, brb." );
|
user.disconnect( getTranslation( "restart" ) );
|
||||||
|
}
|
||||||
|
} finally
|
||||||
|
{
|
||||||
|
connectionLock.readLock().unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
$().info( "Saving reconnect locations" );
|
getLogger().info( "Closing IO threads" );
|
||||||
reconnectHandler.save();
|
eventLoops.shutdownGracefully();
|
||||||
saveThread.cancel();
|
try
|
||||||
|
{
|
||||||
|
eventLoops.awaitTermination( Long.MAX_VALUE, TimeUnit.NANOSECONDS );
|
||||||
|
} catch ( InterruptedException ex )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
$().info( "Disabling plugins" );
|
getLogger().info( "Saving reconnect locations" );
|
||||||
|
reconnectHandler.save();
|
||||||
|
reconnectHandler.close();
|
||||||
|
saveThread.cancel();
|
||||||
|
metricsThread.cancel();
|
||||||
|
|
||||||
|
// TODO: Fix this shit
|
||||||
|
getLogger().info( "Disabling plugins" );
|
||||||
for ( Plugin plugin : pluginManager.getPlugins() )
|
for ( Plugin plugin : pluginManager.getPlugins() )
|
||||||
{
|
{
|
||||||
plugin.onDisable();
|
plugin.onDisable();
|
||||||
|
getScheduler().cancel( plugin );
|
||||||
}
|
}
|
||||||
|
|
||||||
$().info( "Thank you and goodbye" );
|
getLogger().info( "Thankyou and goodbye" );
|
||||||
System.exit( 0 );
|
System.exit( 0 );
|
||||||
}
|
}
|
||||||
|
}.start();
|
||||||
/**
|
|
||||||
* Miscellaneous method to set options on a socket based on those in the
|
|
||||||
* configuration.
|
|
||||||
*
|
|
||||||
* @param socket to set the options on
|
|
||||||
* @throws IOException when the underlying set methods thrown an exception
|
|
||||||
*/
|
|
||||||
public void setSocketOptions(Socket socket) throws IOException
|
|
||||||
{
|
|
||||||
socket.setSoTimeout( config.getTimeout() );
|
|
||||||
socket.setTrafficClass( 0x18 );
|
|
||||||
socket.setTcpNoDelay( true );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -261,10 +349,17 @@ public class BungeeCord extends ProxyServer
|
|||||||
* @param packet the packet to send
|
* @param packet the packet to send
|
||||||
*/
|
*/
|
||||||
public void broadcast(DefinedPacket packet)
|
public void broadcast(DefinedPacket packet)
|
||||||
|
{
|
||||||
|
connectionLock.readLock().lock();
|
||||||
|
try
|
||||||
{
|
{
|
||||||
for ( UserConnection con : connections.values() )
|
for ( UserConnection con : connections.values() )
|
||||||
{
|
{
|
||||||
con.packetQueue.add( packet );
|
con.unsafe().sendPacket( packet );
|
||||||
|
}
|
||||||
|
} finally
|
||||||
|
{
|
||||||
|
connectionLock.readLock().unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -281,29 +376,49 @@ public class BungeeCord extends ProxyServer
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Logger getLogger()
|
public String getTranslation(String name)
|
||||||
{
|
{
|
||||||
return $();
|
String translation = "<translation '" + name + "' missing>";
|
||||||
|
try
|
||||||
|
{
|
||||||
|
translation = bundle.getString( name );
|
||||||
|
} catch ( MissingResourceException ex )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
return translation;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked") // TODO: Abstract more
|
@SuppressWarnings("unchecked")
|
||||||
public Collection<ProxiedPlayer> getPlayers()
|
public Collection<ProxiedPlayer> getPlayers()
|
||||||
{
|
{
|
||||||
return (Collection) connections.values();
|
connectionLock.readLock().lock();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return (Collection) new HashSet<>( connections.values() );
|
||||||
|
} finally
|
||||||
|
{
|
||||||
|
connectionLock.readLock().unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getOnlineCount()
|
||||||
|
{
|
||||||
|
return connections.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ProxiedPlayer getPlayer(String name)
|
public ProxiedPlayer getPlayer(String name)
|
||||||
{
|
{
|
||||||
return connections.get( name );
|
connectionLock.readLock().lock();
|
||||||
}
|
try
|
||||||
|
|
||||||
@Override
|
|
||||||
public Server getServer(String name)
|
|
||||||
{
|
{
|
||||||
Collection<ProxiedPlayer> users = getServers().get( name ).getPlayers();
|
return connections.get( name );
|
||||||
return ( users != null && !users.isEmpty() ) ? users.iterator().next().getServer() : null;
|
} finally
|
||||||
|
{
|
||||||
|
connectionLock.readLock().unlock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -341,31 +456,67 @@ public class BungeeCord extends ProxyServer
|
|||||||
|
|
||||||
public PacketFAPluginMessage registerChannels()
|
public PacketFAPluginMessage registerChannels()
|
||||||
{
|
{
|
||||||
StringBuilder sb = new StringBuilder();
|
return new PacketFAPluginMessage( "REGISTER", Util.format( pluginChannels, "\00" ).getBytes() );
|
||||||
for ( String s : getChannels() )
|
|
||||||
{
|
|
||||||
sb.append( s );
|
|
||||||
sb.append( '\00' );
|
|
||||||
}
|
|
||||||
byte[] payload = sb.substring( 0, sb.length() - 1 ).getBytes();
|
|
||||||
return new PacketFAPluginMessage( "REGISTER", payload );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte getProtocolVersion()
|
public byte getProtocolVersion()
|
||||||
{
|
{
|
||||||
return PROTOCOL_VERSION;
|
return Vanilla.PROTOCOL_VERSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getGameVersion()
|
public String getGameVersion()
|
||||||
{
|
{
|
||||||
return GAME_VERSION;
|
return Vanilla.GAME_VERSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ServerInfo constructServerInfo(String name, InetSocketAddress address)
|
public ServerInfo constructServerInfo(String name, InetSocketAddress address, boolean restricted)
|
||||||
{
|
{
|
||||||
return new BungeeServerInfo( name, address );
|
return new BungeeServerInfo( name, address, restricted );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommandSender getConsole()
|
||||||
|
{
|
||||||
|
return ConsoleCommandSender.getInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void broadcast(String message)
|
||||||
|
{
|
||||||
|
getConsole().sendMessage( message );
|
||||||
|
broadcast( new Packet3Chat( message ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addConnection(UserConnection con)
|
||||||
|
{
|
||||||
|
connectionLock.writeLock().lock();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
connections.put( con.getName(), con );
|
||||||
|
} finally
|
||||||
|
{
|
||||||
|
connectionLock.writeLock().unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeConnection(UserConnection con)
|
||||||
|
{
|
||||||
|
connectionLock.writeLock().lock();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
connections.remove( con.getName() );
|
||||||
|
} finally
|
||||||
|
{
|
||||||
|
connectionLock.writeLock().unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CustomTabList customTabList(ProxiedPlayer player)
|
||||||
|
{
|
||||||
|
return new Custom( player );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,74 +1,131 @@
|
|||||||
package net.md_5.bungee;
|
package net.md_5.bungee;
|
||||||
|
|
||||||
import java.io.DataOutputStream;
|
import com.google.common.base.Preconditions;
|
||||||
|
import io.netty.bootstrap.Bootstrap;
|
||||||
|
import io.netty.channel.ChannelFuture;
|
||||||
|
import io.netty.channel.ChannelFutureListener;
|
||||||
|
import io.netty.channel.ChannelOption;
|
||||||
|
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.Socket;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.Synchronized;
|
||||||
import net.md_5.bungee.api.Callback;
|
import net.md_5.bungee.api.Callback;
|
||||||
import net.md_5.bungee.api.ProxyServer;
|
import net.md_5.bungee.api.CommandSender;
|
||||||
import net.md_5.bungee.api.ServerPing;
|
import net.md_5.bungee.api.ServerPing;
|
||||||
import net.md_5.bungee.api.config.ServerInfo;
|
import net.md_5.bungee.api.config.ServerInfo;
|
||||||
|
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||||
import net.md_5.bungee.api.connection.Server;
|
import net.md_5.bungee.api.connection.Server;
|
||||||
import net.md_5.bungee.packet.DefinedPacket;
|
import net.md_5.bungee.connection.PingHandler;
|
||||||
import net.md_5.bungee.packet.PacketFAPluginMessage;
|
import net.md_5.bungee.netty.HandlerBoss;
|
||||||
import net.md_5.bungee.packet.PacketFFKick;
|
import net.md_5.bungee.netty.PipelineUtils;
|
||||||
import net.md_5.bungee.packet.PacketStream;
|
import net.md_5.bungee.protocol.packet.DefinedPacket;
|
||||||
import net.md_5.mendax.PacketDefinitions;
|
import net.md_5.bungee.protocol.packet.PacketFAPluginMessage;
|
||||||
|
|
||||||
public class BungeeServerInfo extends ServerInfo
|
@RequiredArgsConstructor
|
||||||
|
public class BungeeServerInfo implements ServerInfo
|
||||||
{
|
{
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private final Queue<DefinedPacket> packetQueue = new ConcurrentLinkedQueue<>();
|
private final String name;
|
||||||
|
@Getter
|
||||||
|
private final InetSocketAddress address;
|
||||||
|
private final Collection<ProxiedPlayer> players = new ArrayList<>();
|
||||||
|
@Getter
|
||||||
|
private final boolean restricted;
|
||||||
|
@Getter
|
||||||
|
private final Queue<DefinedPacket> packetQueue = new LinkedList<>();
|
||||||
|
|
||||||
public BungeeServerInfo(String name, InetSocketAddress address)
|
@Synchronized("players")
|
||||||
|
public void addPlayer(ProxiedPlayer player)
|
||||||
{
|
{
|
||||||
super( name, address );
|
players.add( player );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Synchronized("players")
|
||||||
|
public void removePlayer(ProxiedPlayer player)
|
||||||
|
{
|
||||||
|
players.remove( player );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Synchronized("players")
|
||||||
|
@Override
|
||||||
|
public Collection<ProxiedPlayer> getPlayers()
|
||||||
|
{
|
||||||
|
return Collections.unmodifiableCollection( players );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canAccess(CommandSender player)
|
||||||
|
{
|
||||||
|
Preconditions.checkNotNull( player, "player" );
|
||||||
|
return !restricted || player.hasPermission( "bungeecord.server." + name );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj)
|
||||||
|
{
|
||||||
|
return ( obj instanceof ServerInfo ) && Objects.equals( getAddress(), ( (ServerInfo) obj ).getAddress() );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode()
|
||||||
|
{
|
||||||
|
return address.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Don't like this method
|
||||||
@Override
|
@Override
|
||||||
public void sendData(String channel, byte[] data)
|
public void sendData(String channel, byte[] data)
|
||||||
{
|
{
|
||||||
Server server = ProxyServer.getInstance().getServer( getName() );
|
Preconditions.checkNotNull( channel, "channel" );
|
||||||
|
Preconditions.checkNotNull( data, "data" );
|
||||||
|
|
||||||
|
Server server = ( players.isEmpty() ) ? null : players.iterator().next().getServer();
|
||||||
if ( server != null )
|
if ( server != null )
|
||||||
{
|
{
|
||||||
server.sendData( channel, data );
|
server.sendData( channel, data );
|
||||||
} else
|
} else
|
||||||
|
{
|
||||||
|
synchronized ( packetQueue )
|
||||||
{
|
{
|
||||||
packetQueue.add( new PacketFAPluginMessage( channel, data ) );
|
packetQueue.add( new PacketFAPluginMessage( channel, data ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void ping(final Callback<ServerPing> callback)
|
public void ping(final Callback<ServerPing> callback)
|
||||||
{
|
{
|
||||||
new Thread()
|
Preconditions.checkNotNull( callback, "callback" );
|
||||||
|
|
||||||
|
ChannelFutureListener listener = new ChannelFutureListener()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public void run()
|
public void operationComplete(ChannelFuture future) throws Exception
|
||||||
{
|
{
|
||||||
try ( Socket socket = new Socket(); )
|
if ( future.isSuccess() )
|
||||||
{
|
{
|
||||||
socket.connect( getAddress() );
|
future.channel().pipeline().get( HandlerBoss.class ).setHandler( new PingHandler( BungeeServerInfo.this, callback ) );
|
||||||
|
} else
|
||||||
DataOutputStream out = new DataOutputStream( socket.getOutputStream() );
|
|
||||||
out.write( 0xFE );
|
|
||||||
out.write( 0x01 );
|
|
||||||
|
|
||||||
PacketStream in = new PacketStream( socket.getInputStream(), PacketDefinitions.VANILLA_PROTOCOL );
|
|
||||||
PacketFFKick response = new PacketFFKick( in.readPacket() );
|
|
||||||
|
|
||||||
String[] split = response.message.split( "\00" );
|
|
||||||
|
|
||||||
ServerPing ping = new ServerPing( Byte.parseByte( split[1] ), split[2], split[3], Integer.parseInt( split[4] ), Integer.parseInt( split[5] ) );
|
|
||||||
callback.done( ping, null );
|
|
||||||
} catch ( Throwable t )
|
|
||||||
{
|
{
|
||||||
callback.done( null, t );
|
callback.done( null, future.cause() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.start();
|
};
|
||||||
|
new Bootstrap()
|
||||||
|
.channel( NioSocketChannel.class )
|
||||||
|
.group( BungeeCord.getInstance().eventLoops )
|
||||||
|
.handler( PipelineUtils.BASE )
|
||||||
|
.option( ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000 ) // TODO: Configurable
|
||||||
|
.remoteAddress( getAddress() )
|
||||||
|
.connect()
|
||||||
|
.addListener( listener );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,29 +1,22 @@
|
|||||||
package net.md_5.bungee;
|
package net.md_5.bungee;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.security.GeneralSecurityException;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.math.BigInteger;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.net.URLEncoder;
|
|
||||||
import java.security.InvalidAlgorithmParameterException;
|
|
||||||
import java.security.InvalidKeyException;
|
|
||||||
import java.security.Key;
|
import java.security.Key;
|
||||||
|
import java.security.KeyFactory;
|
||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
import java.security.KeyPairGenerator;
|
import java.security.KeyPairGenerator;
|
||||||
import java.security.MessageDigest;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.PublicKey;
|
||||||
|
import java.security.spec.X509EncodedKeySpec;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import javax.crypto.BadPaddingException;
|
|
||||||
import javax.crypto.Cipher;
|
import javax.crypto.Cipher;
|
||||||
import javax.crypto.IllegalBlockSizeException;
|
|
||||||
import javax.crypto.NoSuchPaddingException;
|
|
||||||
import javax.crypto.SecretKey;
|
import javax.crypto.SecretKey;
|
||||||
import javax.crypto.spec.IvParameterSpec;
|
import javax.crypto.spec.IvParameterSpec;
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
import net.md_5.bungee.packet.PacketFCEncryptionResponse;
|
import lombok.Getter;
|
||||||
import net.md_5.bungee.packet.PacketFDEncryptionRequest;
|
import net.md_5.bungee.protocol.packet.PacketFCEncryptionResponse;
|
||||||
|
import net.md_5.bungee.protocol.packet.PacketFDEncryptionRequest;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class containing all encryption related methods for the proxy.
|
* Class containing all encryption related methods for the proxy.
|
||||||
@@ -32,15 +25,23 @@ public class EncryptionUtil
|
|||||||
{
|
{
|
||||||
|
|
||||||
private static final Random random = new Random();
|
private static final Random random = new Random();
|
||||||
private static KeyPair keys;
|
public static KeyPair keys;
|
||||||
|
@Getter
|
||||||
|
private static SecretKey secret = new SecretKeySpec( new byte[ 16 ], "AES" );
|
||||||
|
|
||||||
public static PacketFDEncryptionRequest encryptRequest() throws NoSuchAlgorithmException
|
static
|
||||||
{
|
{
|
||||||
if ( keys == null )
|
try
|
||||||
{
|
{
|
||||||
keys = KeyPairGenerator.getInstance( "RSA" ).generateKeyPair();
|
keys = KeyPairGenerator.getInstance( "RSA" ).generateKeyPair();
|
||||||
|
} catch ( NoSuchAlgorithmException ex )
|
||||||
|
{
|
||||||
|
throw new ExceptionInInitializerError( ex );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static PacketFDEncryptionRequest encryptRequest()
|
||||||
|
{
|
||||||
String hash = ( BungeeCord.getInstance().config.isOnlineMode() ) ? Long.toString( random.nextLong(), 16 ) : "-";
|
String hash = ( BungeeCord.getInstance().config.isOnlineMode() ) ? Long.toString( random.nextLong(), 16 ) : "-";
|
||||||
byte[] pubKey = keys.getPublic().getEncoded();
|
byte[] pubKey = keys.getPublic().getEncoded();
|
||||||
byte[] verify = new byte[ 4 ];
|
byte[] verify = new byte[ 4 ];
|
||||||
@@ -48,52 +49,37 @@ public class EncryptionUtil
|
|||||||
return new PacketFDEncryptionRequest( hash, pubKey, verify );
|
return new PacketFDEncryptionRequest( hash, pubKey, verify );
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SecretKey getSecret(PacketFCEncryptionResponse resp, PacketFDEncryptionRequest request) throws BadPaddingException, IllegalBlockSizeException, IllegalStateException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException
|
public static SecretKey getSecret(PacketFCEncryptionResponse resp, PacketFDEncryptionRequest request) throws GeneralSecurityException
|
||||||
{
|
{
|
||||||
Cipher cipher = Cipher.getInstance( "RSA" );
|
Cipher cipher = Cipher.getInstance( "RSA" );
|
||||||
cipher.init( Cipher.DECRYPT_MODE, keys.getPrivate() );
|
cipher.init( Cipher.DECRYPT_MODE, keys.getPrivate() );
|
||||||
byte[] decrypted = cipher.doFinal( resp.verifyToken );
|
byte[] decrypted = cipher.doFinal( resp.getVerifyToken() );
|
||||||
|
|
||||||
if ( !Arrays.equals( request.verifyToken, decrypted ) )
|
if ( !Arrays.equals( request.getVerifyToken(), decrypted ) )
|
||||||
{
|
{
|
||||||
throw new IllegalStateException( "Key pairs do not match!" );
|
throw new IllegalStateException( "Key pairs do not match!" );
|
||||||
}
|
}
|
||||||
|
|
||||||
cipher.init( Cipher.DECRYPT_MODE, keys.getPrivate() );
|
cipher.init( Cipher.DECRYPT_MODE, keys.getPrivate() );
|
||||||
byte[] shared = resp.sharedSecret;
|
return new SecretKeySpec( cipher.doFinal( resp.getSharedSecret() ), "AES" );
|
||||||
byte[] secret = cipher.doFinal( shared );
|
|
||||||
|
|
||||||
return new SecretKeySpec( secret, "AES" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isAuthenticated(String username, String connectionHash, SecretKey shared) throws NoSuchAlgorithmException, IOException
|
public static Cipher getCipher(int opMode, Key shared) throws GeneralSecurityException
|
||||||
{
|
|
||||||
String encName = URLEncoder.encode( username, "UTF-8" );
|
|
||||||
|
|
||||||
MessageDigest sha = MessageDigest.getInstance( "SHA-1" );
|
|
||||||
for ( byte[] bit : new byte[][]
|
|
||||||
{
|
|
||||||
connectionHash.getBytes( "ISO_8859_1" ), shared.getEncoded(), keys.getPublic().getEncoded()
|
|
||||||
} )
|
|
||||||
{
|
|
||||||
sha.update( bit );
|
|
||||||
}
|
|
||||||
|
|
||||||
String encodedHash = URLEncoder.encode( new BigInteger( sha.digest() ).toString( 16 ), "UTF-8" );
|
|
||||||
String authURL = "http://session.minecraft.net/game/checkserver.jsp?user=" + encName + "&serverId=" + encodedHash;
|
|
||||||
String reply;
|
|
||||||
try ( BufferedReader in = new BufferedReader( new InputStreamReader( new URL( authURL ).openStream() ) ) )
|
|
||||||
{
|
|
||||||
reply = in.readLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
return "YES".equals( reply );
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Cipher getCipher(int opMode, Key shared) throws InvalidAlgorithmParameterException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException
|
|
||||||
{
|
{
|
||||||
Cipher cip = Cipher.getInstance( "AES/CFB8/NoPadding" );
|
Cipher cip = Cipher.getInstance( "AES/CFB8/NoPadding" );
|
||||||
cip.init( opMode, shared, new IvParameterSpec( shared.getEncoded() ) );
|
cip.init( opMode, shared, new IvParameterSpec( shared.getEncoded() ) );
|
||||||
return cip;
|
return cip;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static PublicKey getPubkey(PacketFDEncryptionRequest request) throws GeneralSecurityException
|
||||||
|
{
|
||||||
|
return KeyFactory.getInstance( "RSA" ).generatePublic( new X509EncodedKeySpec( request.getPublicKey() ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] encrypt(Key key, byte[] b) throws GeneralSecurityException
|
||||||
|
{
|
||||||
|
Cipher hasher = Cipher.getInstance( "RSA" );
|
||||||
|
hasher.init( Cipher.ENCRYPT_MODE, key );
|
||||||
|
return hasher.doFinal( b );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -40,7 +40,7 @@ public class EntityMap
|
|||||||
};
|
};
|
||||||
entityIds[0x17] = new int[]
|
entityIds[0x17] = new int[]
|
||||||
{
|
{
|
||||||
1, 20
|
1 //, 20
|
||||||
};
|
};
|
||||||
entityIds[0x18] = new int[]
|
entityIds[0x18] = new int[]
|
||||||
{
|
{
|
||||||
@@ -115,7 +115,7 @@ public class EntityMap
|
|||||||
|
|
||||||
public static void rewrite(byte[] packet, int oldId, int newId)
|
public static void rewrite(byte[] packet, int oldId, int newId)
|
||||||
{
|
{
|
||||||
int packetId = Util.getId( packet );
|
int packetId = packet[0] & 0xFF;
|
||||||
if ( packetId == 0x1D )
|
if ( packetId == 0x1D )
|
||||||
{ // bulk entity
|
{ // bulk entity
|
||||||
for ( int pos = 2; pos < packet.length; pos += 4 )
|
for ( int pos = 2; pos < packet.length; pos += 4 )
|
||||||
@@ -147,6 +147,18 @@ public class EntityMap
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ( packetId == 0x17 )
|
||||||
|
{
|
||||||
|
int type = packet[5] & 0xFF;
|
||||||
|
if ( type == 60 || type == 90 )
|
||||||
|
{
|
||||||
|
int index20 = readInt( packet, 20 );
|
||||||
|
if ( packet.length > 24 && index20 == oldId )
|
||||||
|
{
|
||||||
|
setInt( packet, 20, newId );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void setInt(byte[] buf, int pos, int i)
|
private static void setInt(byte[] buf, int pos, int i)
|
||||||
|
@@ -1,61 +0,0 @@
|
|||||||
package net.md_5.bungee;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.net.Socket;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import static net.md_5.bungee.Logger.$;
|
|
||||||
import net.md_5.bungee.packet.PacketFFKick;
|
|
||||||
import net.md_5.bungee.packet.PacketStream;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class to represent a Minecraft connection.
|
|
||||||
*/
|
|
||||||
@EqualsAndHashCode
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class GenericConnection
|
|
||||||
{
|
|
||||||
|
|
||||||
protected final Socket socket;
|
|
||||||
protected final PacketStream stream;
|
|
||||||
@Getter
|
|
||||||
public String name;
|
|
||||||
@Getter
|
|
||||||
public String displayName;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Close the socket with the specified reason.
|
|
||||||
*
|
|
||||||
* @param reason to disconnect
|
|
||||||
*/
|
|
||||||
public void disconnect(String reason)
|
|
||||||
{
|
|
||||||
if ( socket.isClosed() )
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
log( "disconnected with " + reason );
|
|
||||||
try
|
|
||||||
{
|
|
||||||
stream.write( new PacketFFKick( "[Proxy] " + reason ) );
|
|
||||||
} catch ( IOException ex )
|
|
||||||
{
|
|
||||||
} finally
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
socket.shutdownOutput();
|
|
||||||
socket.close();
|
|
||||||
} catch ( IOException ioe )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void log(String message)
|
|
||||||
{
|
|
||||||
$().info( socket.getInetAddress() + ( ( name == null ) ? " " : " [" + name + "] " ) + message );
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,232 +0,0 @@
|
|||||||
package net.md_5.bungee;
|
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
|
||||||
import java.io.EOFException;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.net.Socket;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import javax.crypto.Cipher;
|
|
||||||
import javax.crypto.CipherInputStream;
|
|
||||||
import javax.crypto.CipherOutputStream;
|
|
||||||
import javax.crypto.SecretKey;
|
|
||||||
import lombok.Getter;
|
|
||||||
import net.md_5.bungee.api.ChatColor;
|
|
||||||
import net.md_5.bungee.api.ProxyServer;
|
|
||||||
import net.md_5.bungee.api.ServerPing;
|
|
||||||
import net.md_5.bungee.api.config.ListenerInfo;
|
|
||||||
import net.md_5.bungee.api.config.ServerInfo;
|
|
||||||
import net.md_5.bungee.api.connection.PendingConnection;
|
|
||||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
|
||||||
import net.md_5.bungee.api.event.LoginEvent;
|
|
||||||
import net.md_5.bungee.api.event.ProxyPingEvent;
|
|
||||||
import net.md_5.bungee.packet.DefinedPacket;
|
|
||||||
import net.md_5.bungee.packet.Packet1Login;
|
|
||||||
import net.md_5.bungee.packet.Packet2Handshake;
|
|
||||||
import net.md_5.bungee.packet.PacketCDClientStatus;
|
|
||||||
import net.md_5.bungee.packet.PacketFAPluginMessage;
|
|
||||||
import net.md_5.bungee.packet.PacketFCEncryptionResponse;
|
|
||||||
import net.md_5.bungee.packet.PacketFDEncryptionRequest;
|
|
||||||
import net.md_5.bungee.packet.PacketFEPing;
|
|
||||||
import net.md_5.bungee.packet.PacketFFKick;
|
|
||||||
import net.md_5.bungee.packet.PacketHandler;
|
|
||||||
import net.md_5.bungee.packet.PacketStream;
|
|
||||||
import net.md_5.mendax.PacketDefinitions;
|
|
||||||
|
|
||||||
public class InitialHandler extends PacketHandler implements Runnable, PendingConnection
|
|
||||||
{
|
|
||||||
|
|
||||||
private final Socket socket;
|
|
||||||
@Getter
|
|
||||||
private final ListenerInfo listener;
|
|
||||||
private PacketStream stream;
|
|
||||||
private Packet1Login forgeLogin;
|
|
||||||
private Packet2Handshake handshake;
|
|
||||||
private PacketFDEncryptionRequest request;
|
|
||||||
private List<PacketFAPluginMessage> loginMessages = new ArrayList<>();
|
|
||||||
private State thisState = State.HANDSHAKE;
|
|
||||||
private static final PacketFAPluginMessage forgeMods = new PacketFAPluginMessage( "FML", new byte[]
|
|
||||||
{
|
|
||||||
0, 0, 0, 0, 0, 2
|
|
||||||
} );
|
|
||||||
|
|
||||||
public InitialHandler(Socket socket, ListenerInfo info) throws IOException
|
|
||||||
{
|
|
||||||
this.socket = socket;
|
|
||||||
this.listener = info;
|
|
||||||
stream = new PacketStream( socket.getInputStream(), socket.getOutputStream(), PacketDefinitions.VANILLA_PROTOCOL );
|
|
||||||
}
|
|
||||||
|
|
||||||
private enum State
|
|
||||||
{
|
|
||||||
|
|
||||||
HANDSHAKE, ENCRYPT, LOGIN, FINISHED;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void handle(Packet1Login login) throws Exception
|
|
||||||
{
|
|
||||||
Preconditions.checkState( thisState == State.LOGIN, "Not expecting FORGE LOGIN" );
|
|
||||||
Preconditions.checkState( forgeLogin == null, "Already received FORGE LOGIN" );
|
|
||||||
forgeLogin = login;
|
|
||||||
stream.setProtocol( PacketDefinitions.FORGE_PROTOCOL );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void handle(PacketFAPluginMessage pluginMessage) throws Exception
|
|
||||||
{
|
|
||||||
loginMessages.add( pluginMessage );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void handle(PacketFEPing ping) throws Exception
|
|
||||||
{
|
|
||||||
socket.setSoTimeout( 100 );
|
|
||||||
boolean newPing = false;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
socket.getInputStream().read();
|
|
||||||
newPing = true;
|
|
||||||
} catch ( IOException ex )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
ServerPing pingevent = new ServerPing( BungeeCord.PROTOCOL_VERSION, BungeeCord.GAME_VERSION,
|
|
||||||
listener.getMotd(), ProxyServer.getInstance().getPlayers().size(), listener.getMaxPlayers() );
|
|
||||||
|
|
||||||
pingevent = ProxyServer.getInstance().getPluginManager().callEvent( new ProxyPingEvent( this, pingevent ) ).getResponse();
|
|
||||||
|
|
||||||
String response = ( newPing ) ? ChatColor.COLOR_CHAR + "1"
|
|
||||||
+ "\00" + pingevent.getProtocolVersion()
|
|
||||||
+ "\00" + pingevent.getGameVersion()
|
|
||||||
+ "\00" + pingevent.getMotd()
|
|
||||||
+ "\00" + pingevent.getCurrentPlayers()
|
|
||||||
+ "\00" + pingevent.getMaxPlayers()
|
|
||||||
: pingevent.getMotd() + ChatColor.COLOR_CHAR + pingevent.getCurrentPlayers() + ChatColor.COLOR_CHAR + pingevent.getMaxPlayers();
|
|
||||||
disconnect( response );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void handle(Packet2Handshake handshake) throws Exception
|
|
||||||
{
|
|
||||||
Preconditions.checkState( thisState == State.HANDSHAKE, "Not expecting HANDSHAKE" );
|
|
||||||
this.handshake = handshake;
|
|
||||||
stream.write( forgeMods );
|
|
||||||
stream.write( request = EncryptionUtil.encryptRequest() );
|
|
||||||
thisState = State.ENCRYPT;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void handle(PacketFCEncryptionResponse encryptResponse) throws Exception
|
|
||||||
{
|
|
||||||
Preconditions.checkState( thisState == State.ENCRYPT, "Not expecting ENCRYPT" );
|
|
||||||
|
|
||||||
SecretKey shared = EncryptionUtil.getSecret( encryptResponse, request );
|
|
||||||
if ( BungeeCord.getInstance().config.isOnlineMode() && !EncryptionUtil.isAuthenticated( handshake.username, request.serverId, shared ) )
|
|
||||||
{
|
|
||||||
throw new KickException( "Not authenticated with minecraft.net" );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for multiple connections
|
|
||||||
ProxiedPlayer old = ProxyServer.getInstance().getPlayer( handshake.username );
|
|
||||||
if ( old != null )
|
|
||||||
{
|
|
||||||
old.disconnect( "You are already connected to the server" );
|
|
||||||
}
|
|
||||||
|
|
||||||
// fire login event
|
|
||||||
LoginEvent event = new LoginEvent( this );
|
|
||||||
ProxyServer.getInstance().getPluginManager().callEvent( event );
|
|
||||||
if ( event.isCancelled() )
|
|
||||||
{
|
|
||||||
throw new KickException( event.getCancelReason() );
|
|
||||||
}
|
|
||||||
|
|
||||||
stream.write( new PacketFCEncryptionResponse() );
|
|
||||||
stream = new PacketStream( new CipherInputStream( socket.getInputStream(), EncryptionUtil.getCipher( Cipher.DECRYPT_MODE, shared ) ),
|
|
||||||
new CipherOutputStream( socket.getOutputStream(), EncryptionUtil.getCipher( Cipher.ENCRYPT_MODE, shared ) ), stream.getProtocol() );
|
|
||||||
|
|
||||||
thisState = State.LOGIN;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void handle(PacketCDClientStatus clientStatus) throws Exception
|
|
||||||
{
|
|
||||||
Preconditions.checkState( thisState == State.LOGIN, "Not expecting LOGIN" );
|
|
||||||
|
|
||||||
UserConnection userCon = new UserConnection( socket, this, stream, handshake, forgeLogin, loginMessages );
|
|
||||||
ServerInfo server = ProxyServer.getInstance().getReconnectHandler().getServer( userCon );
|
|
||||||
userCon.connect( server, true );
|
|
||||||
|
|
||||||
thisState = State.FINISHED;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
while ( thisState != State.FINISHED )
|
|
||||||
{
|
|
||||||
byte[] buf = stream.readPacket();
|
|
||||||
DefinedPacket packet = DefinedPacket.packet( buf );
|
|
||||||
packet.handle( this );
|
|
||||||
}
|
|
||||||
} catch ( KickException ex )
|
|
||||||
{
|
|
||||||
disconnect( "[Proxy - Kicked] " + ex.getMessage() );
|
|
||||||
} catch ( EOFException ex )
|
|
||||||
{
|
|
||||||
} catch ( Exception ex )
|
|
||||||
{
|
|
||||||
disconnect( "[Proxy Error] " + Util.exception( ex ) );
|
|
||||||
ex.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void disconnect(String reason)
|
|
||||||
{
|
|
||||||
thisState = State.FINISHED;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
stream.write( new PacketFFKick( reason ) );
|
|
||||||
} catch ( IOException ioe )
|
|
||||||
{
|
|
||||||
} finally
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
socket.shutdownOutput();
|
|
||||||
socket.close();
|
|
||||||
} catch ( IOException ioe2 )
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName()
|
|
||||||
{
|
|
||||||
return ( handshake == null ) ? null : handshake.username;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte getVersion()
|
|
||||||
{
|
|
||||||
return ( handshake == null ) ? -1 : handshake.procolVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public InetSocketAddress getVirtualHost()
|
|
||||||
{
|
|
||||||
return ( handshake == null ) ? null : new InetSocketAddress( handshake.host, handshake.port );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public InetSocketAddress getAddress()
|
|
||||||
{
|
|
||||||
return (InetSocketAddress) socket.getRemoteSocketAddress();
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,14 +0,0 @@
|
|||||||
package net.md_5.bungee;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Exception, which when thrown will disconnect the player from the proxy with
|
|
||||||
* the specified message.
|
|
||||||
*/
|
|
||||||
public class KickException extends RuntimeException
|
|
||||||
{
|
|
||||||
|
|
||||||
public KickException(String message)
|
|
||||||
{
|
|
||||||
super( message );
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,48 +0,0 @@
|
|||||||
package net.md_5.bungee;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.ServerSocket;
|
|
||||||
import java.net.Socket;
|
|
||||||
import java.net.SocketException;
|
|
||||||
import static net.md_5.bungee.Logger.$;
|
|
||||||
import net.md_5.bungee.api.config.ListenerInfo;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Thread to listen and dispatch incoming connections to the proxy.
|
|
||||||
*/
|
|
||||||
public class ListenThread extends Thread
|
|
||||||
{
|
|
||||||
|
|
||||||
public final ServerSocket socket;
|
|
||||||
private final ListenerInfo info;
|
|
||||||
|
|
||||||
public ListenThread(ListenerInfo info) throws IOException
|
|
||||||
{
|
|
||||||
super( "Listen Thread - " + info );
|
|
||||||
this.info = info;
|
|
||||||
socket = new ServerSocket();
|
|
||||||
socket.bind( info.getHost() );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run()
|
|
||||||
{
|
|
||||||
while ( !isInterrupted() )
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Socket client = socket.accept();
|
|
||||||
BungeeCord.getInstance().setSocketOptions( client );
|
|
||||||
$().info( client.getInetAddress() + " has connected" );
|
|
||||||
InitialHandler handler = new InitialHandler( client, info );
|
|
||||||
BungeeCord.getInstance().threadPool.submit( handler );
|
|
||||||
} catch ( SocketException ex )
|
|
||||||
{
|
|
||||||
ex.printStackTrace(); // Now people can see why their operating system is failing them and stop bitching at me!
|
|
||||||
} catch ( IOException ex )
|
|
||||||
{
|
|
||||||
ex.printStackTrace(); // TODO
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,109 +0,0 @@
|
|||||||
package net.md_5.bungee;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.io.StringWriter;
|
|
||||||
import java.text.MessageFormat;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.logging.FileHandler;
|
|
||||||
import java.util.logging.Formatter;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.LogRecord;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Logger to handle formatting and storage of the proxy's logger.
|
|
||||||
*/
|
|
||||||
public class Logger extends java.util.logging.Logger
|
|
||||||
{
|
|
||||||
|
|
||||||
private static final Formatter formatter = new ConsoleLogFormatter();
|
|
||||||
private static final Logger instance = new Logger();
|
|
||||||
|
|
||||||
public Logger()
|
|
||||||
{
|
|
||||||
super( "RubberBand", null );
|
|
||||||
try
|
|
||||||
{
|
|
||||||
FileHandler handler = new FileHandler( "proxy.log", 1 << 14, 1, true );
|
|
||||||
handler.setFormatter( formatter );
|
|
||||||
addHandler( handler );
|
|
||||||
} catch ( IOException ex )
|
|
||||||
{
|
|
||||||
System.err.println( "Could not register logger!" );
|
|
||||||
ex.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void log(LogRecord record)
|
|
||||||
{
|
|
||||||
super.log( record );
|
|
||||||
String message = formatter.format( record );
|
|
||||||
if ( record.getLevel() == Level.SEVERE || record.getLevel() == Level.WARNING )
|
|
||||||
{
|
|
||||||
System.err.print( message );
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
System.out.print( message );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the current logger instance.
|
|
||||||
*
|
|
||||||
* @return the current logger instance
|
|
||||||
*/
|
|
||||||
public static Logger $()
|
|
||||||
{
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ConsoleLogFormatter extends Formatter
|
|
||||||
{
|
|
||||||
|
|
||||||
private SimpleDateFormat formatter = new SimpleDateFormat( "HH:mm:ss" );
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String format(LogRecord logrecord)
|
|
||||||
{
|
|
||||||
StringBuilder formatted = new StringBuilder();
|
|
||||||
|
|
||||||
formatted.append( formatter.format( logrecord.getMillis() ) );
|
|
||||||
Level level = logrecord.getLevel();
|
|
||||||
|
|
||||||
if ( level == Level.FINEST )
|
|
||||||
{
|
|
||||||
formatted.append( " [FINEST] " );
|
|
||||||
} else if ( level == Level.FINER )
|
|
||||||
{
|
|
||||||
formatted.append( " [FINER] " );
|
|
||||||
} else if ( level == Level.FINE )
|
|
||||||
{
|
|
||||||
formatted.append( " [FINE] " );
|
|
||||||
} else if ( level == Level.INFO )
|
|
||||||
{
|
|
||||||
formatted.append( " [INFO] " );
|
|
||||||
} else if ( level == Level.WARNING )
|
|
||||||
{
|
|
||||||
formatted.append( " [WARNING] " );
|
|
||||||
} else if ( level == Level.SEVERE )
|
|
||||||
{
|
|
||||||
formatted.append( " [SEVERE] " );
|
|
||||||
}
|
|
||||||
|
|
||||||
formatted.append( formatMessage( logrecord ) );
|
|
||||||
formatted.append( '\n' );
|
|
||||||
Throwable throwable = logrecord.getThrown();
|
|
||||||
|
|
||||||
if ( throwable != null )
|
|
||||||
{
|
|
||||||
StringWriter writer = new StringWriter();
|
|
||||||
|
|
||||||
throwable.printStackTrace( new PrintWriter( writer ) );
|
|
||||||
formatted.append( writer );
|
|
||||||
}
|
|
||||||
|
|
||||||
return formatted.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user