Compare commits
295 Commits
Minecraft-
...
Minecraft-
Author | SHA1 | Date | |
---|---|---|---|
![]() |
db5510cc4e | ||
![]() |
5ed5c71aea | ||
![]() |
38a8469ab4 | ||
![]() |
9538dcf4d4 | ||
![]() |
33f654ce6f | ||
![]() |
c108e4e1ce | ||
![]() |
e998faeec1 | ||
![]() |
d67acd7bc9 | ||
![]() |
702f434db1 | ||
![]() |
47b5631562 | ||
![]() |
80e23d6646 | ||
![]() |
1dca12cffb | ||
![]() |
29c897c9cf | ||
![]() |
042f47cbb9 | ||
![]() |
422e97f495 | ||
![]() |
08789d8f9f | ||
![]() |
96444ae304 | ||
![]() |
af58db8a67 | ||
![]() |
49cffebd9b | ||
![]() |
ffdb917f2c | ||
![]() |
9c9657e36d | ||
![]() |
1342baed47 | ||
![]() |
e3a7490bcd | ||
![]() |
3e8693793c | ||
![]() |
bb47aba682 | ||
![]() |
d0e5ee4e09 | ||
![]() |
07e330b005 | ||
![]() |
024288e587 | ||
![]() |
53a6bb1dee | ||
![]() |
0f06b2c4e0 | ||
![]() |
d3c1acce83 | ||
![]() |
eaea090d37 | ||
![]() |
7384e797fc | ||
![]() |
d4d93ddbb9 | ||
![]() |
ccdf2a89d8 | ||
![]() |
89edb00c05 | ||
![]() |
00a0277a13 | ||
![]() |
68f11e46f7 | ||
![]() |
c352e854ee | ||
![]() |
d8c92cd311 | ||
![]() |
99f361ca77 | ||
![]() |
738ed99d54 | ||
![]() |
ad0da59267 | ||
![]() |
1dcc8d6a4b | ||
![]() |
0840a77153 | ||
![]() |
61a93a54a9 | ||
![]() |
da0281508e | ||
![]() |
51e92de2dd | ||
![]() |
f948acd634 | ||
![]() |
773ce089c1 | ||
![]() |
a07eba7965 | ||
![]() |
b68b6a76c7 | ||
![]() |
332033bb02 | ||
![]() |
172b8bc75b | ||
![]() |
db5a147491 | ||
![]() |
f083e27649 | ||
![]() |
b64a7be19b | ||
![]() |
c4d60a8fa9 | ||
![]() |
f07cfe0cf7 | ||
![]() |
4463b0c1b2 | ||
![]() |
ee8f33c196 | ||
![]() |
14ac2dd308 | ||
![]() |
fb94612315 | ||
![]() |
4c96880580 | ||
![]() |
4c4cdd51a1 | ||
![]() |
1f38152530 | ||
![]() |
911f08d52c | ||
![]() |
8f961c9d4e | ||
![]() |
8a5d8a57f7 | ||
![]() |
c54553d0f9 | ||
![]() |
600a1b4ff5 | ||
![]() |
09e592295f | ||
![]() |
fa0ee02beb | ||
![]() |
b23b54d9e4 | ||
![]() |
b3e8feb4cb | ||
![]() |
d0d1562155 | ||
![]() |
f510ab2a0b | ||
![]() |
fb1cab499d | ||
![]() |
58ca63e2b1 | ||
![]() |
499337c98e | ||
![]() |
526137be7b | ||
![]() |
47839cb11c | ||
![]() |
55a6cc56ef | ||
![]() |
8c2bea5be2 | ||
![]() |
daa58ffe58 | ||
![]() |
0189ad9c17 | ||
![]() |
9adcb05d45 | ||
![]() |
10e81041b2 | ||
![]() |
0c56945ffd | ||
![]() |
0a36cbd5bc | ||
![]() |
61b4777177 | ||
![]() |
7d1904584b | ||
![]() |
475571986c | ||
![]() |
55c2bcd634 | ||
![]() |
db4abfe486 | ||
![]() |
9424bdedca | ||
![]() |
52b3c6b77c | ||
![]() |
be29799f5a | ||
![]() |
c0d581d41f | ||
![]() |
6b50c7c599 | ||
![]() |
b4101874cc | ||
![]() |
66de4c95ef | ||
![]() |
927a295add | ||
![]() |
2cbea83c02 | ||
![]() |
87884ad084 | ||
![]() |
94cc2412e7 | ||
![]() |
924b90e325 | ||
![]() |
3f476a30b4 | ||
![]() |
f579b31bca | ||
![]() |
cac35116c3 | ||
![]() |
bd42fb23a0 | ||
![]() |
ffbebaff69 | ||
![]() |
b741722e5d | ||
![]() |
07288c722c | ||
![]() |
85e82a2e34 | ||
![]() |
3aef35ccbb | ||
![]() |
d1760dad93 | ||
![]() |
d3d11cf283 | ||
![]() |
d3bada58d4 | ||
![]() |
23517a9a97 | ||
![]() |
fdc87e88f5 | ||
![]() |
12941ffe62 | ||
![]() |
06e732d8c7 | ||
![]() |
5c4ea3c7a0 | ||
![]() |
632fa8bd94 | ||
![]() |
8732904bfd | ||
![]() |
788b96dc0a | ||
![]() |
1296783d9b | ||
![]() |
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 |
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1,12 +1,11 @@
|
||||
# Eclipse stuff
|
||||
.classpath/
|
||||
.project/
|
||||
.classpath
|
||||
.project
|
||||
.settings/
|
||||
|
||||
# netbeans
|
||||
nbproject/
|
||||
nbactions.xml
|
||||
nb-configuration.xml
|
||||
|
||||
# we use maven!
|
||||
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>
|
16
api/pom.xml
16
api/pom.xml
@@ -6,13 +6,13 @@
|
||||
<parent>
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-parent</artifactId>
|
||||
<version>1.5-SNAPSHOT</version>
|
||||
<version>1.6.2-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-api</artifactId>
|
||||
<version>1.5-SNAPSHOT</version>
|
||||
<version>1.6.2-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>BungeeCord-API</name>
|
||||
@@ -26,9 +26,15 @@
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.ning</groupId>
|
||||
<artifactId>async-http-client</artifactId>
|
||||
<version>1.7.14</version>
|
||||
<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>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
@@ -1,111 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Guava Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.common.eventbus;
|
||||
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.reflect.TypeToken;
|
||||
import com.google.common.util.concurrent.UncheckedExecutionException;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A {@link HandlerFindingStrategy} for collecting all event handler methods that are marked with
|
||||
* the {@link Subscribe} annotation.
|
||||
*
|
||||
* @author Cliff Biffle
|
||||
* @author Louis Wasserman
|
||||
*/
|
||||
class AnnotatedHandlerFinder implements HandlerFindingStrategy {
|
||||
/**
|
||||
* A thread-safe cache that contains the mapping from each class to all methods in that class and
|
||||
* all super-classes, that are annotated with {@code @Subscribe}. The cache is shared across all
|
||||
* instances of this class; this greatly improves performance if multiple EventBus instances are
|
||||
* created and objects of the same class are registered on all of them.
|
||||
*/
|
||||
private static final LoadingCache<Class<?>, ImmutableList<Method>> handlerMethodsCache =
|
||||
CacheBuilder.newBuilder()
|
||||
.weakKeys()
|
||||
.build(new CacheLoader<Class<?>, ImmutableList<Method>>() {
|
||||
@Override
|
||||
public ImmutableList<Method> load(Class<?> concreteClass) throws Exception {
|
||||
return getAnnotatedMethodsInternal(concreteClass);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* This implementation finds all methods marked with a {@link Subscribe} annotation.
|
||||
*/
|
||||
@Override
|
||||
public Multimap<Class<?>, EventHandler> findAllHandlers(Object listener) {
|
||||
Multimap<Class<?>, EventHandler> methodsInListener = HashMultimap.create();
|
||||
Class<?> clazz = listener.getClass();
|
||||
for (Method method : getAnnotatedMethods(clazz)) {
|
||||
Class<?>[] parameterTypes = method.getParameterTypes();
|
||||
Class<?> eventType = parameterTypes[0];
|
||||
EventHandler handler = new EventHandler(listener, method);
|
||||
methodsInListener.put(eventType, handler);
|
||||
}
|
||||
return methodsInListener;
|
||||
}
|
||||
|
||||
private static ImmutableList<Method> getAnnotatedMethods(Class<?> clazz) {
|
||||
try {
|
||||
return handlerMethodsCache.getUnchecked(clazz);
|
||||
} catch (UncheckedExecutionException e) {
|
||||
throw Throwables.propagate(e.getCause());
|
||||
}
|
||||
}
|
||||
|
||||
private static ImmutableList<Method> getAnnotatedMethodsInternal(Class<?> clazz) {
|
||||
Set<? extends Class<?>> supers = TypeToken.of(clazz).getTypes().rawTypes();
|
||||
ImmutableList.Builder<Method> result = ImmutableList.builder();
|
||||
for (Method method : clazz.getMethods()) {
|
||||
/*
|
||||
* Iterate over each distinct method of {@code clazz}, checking if it is annotated with
|
||||
* @Subscribe by any of the superclasses or superinterfaces that declare it.
|
||||
*/
|
||||
for (Class<?> c : supers) {
|
||||
try {
|
||||
Method m = c.getMethod(method.getName(), method.getParameterTypes());
|
||||
if (m.isAnnotationPresent(Subscribe.class)) {
|
||||
Class<?>[] parameterTypes = method.getParameterTypes();
|
||||
if (parameterTypes.length != 1) {
|
||||
throw new IllegalArgumentException("Method " + method
|
||||
+ " has @Subscribe annotation, but requires " + parameterTypes.length
|
||||
+ " arguments. Event handler methods must require a single argument.");
|
||||
}
|
||||
Class<?> eventType = parameterTypes[0];
|
||||
result.add(method);
|
||||
break;
|
||||
}
|
||||
} catch (NoSuchMethodException ignored) {
|
||||
// Move on.
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.build();
|
||||
}
|
||||
}
|
@@ -0,0 +1,46 @@
|
||||
package net.md_5.bungee.api;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import net.md_5.bungee.api.config.ServerInfo;
|
||||
import net.md_5.bungee.api.connection.PendingConnection;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
|
||||
public abstract class AbstractReconnectHandler implements ReconnectHandler
|
||||
{
|
||||
|
||||
@Override
|
||||
public ServerInfo getServer(ProxiedPlayer player)
|
||||
{
|
||||
ServerInfo server = getForcedHost( player.getPendingConnection() );
|
||||
if ( server == null )
|
||||
{
|
||||
server = getStoredServer( player );
|
||||
if ( server == null )
|
||||
{
|
||||
server = ProxyServer.getInstance().getServerInfo( player.getPendingConnection().getListener().getDefaultServer() );
|
||||
}
|
||||
|
||||
Preconditions.checkState( server != null, "Default server not defined" );
|
||||
}
|
||||
|
||||
return server;
|
||||
}
|
||||
|
||||
public static ServerInfo getForcedHost(PendingConnection con)
|
||||
{
|
||||
if ( con.getVirtualHost() == null )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
String forced = con.getListener().getForcedHosts().get( con.getVirtualHost().getHostString() );
|
||||
|
||||
if ( forced == null && con.getListener().isForceDefault() )
|
||||
{
|
||||
forced = con.getListener().getDefaultServer();
|
||||
}
|
||||
return ProxyServer.getInstance().getServerInfo( forced );
|
||||
}
|
||||
|
||||
protected abstract ServerInfo getStoredServer(ProxiedPlayer player);
|
||||
}
|
@@ -2,7 +2,6 @@ package net.md_5.bungee.api;
|
||||
|
||||
import net.md_5.bungee.api.plugin.PluginManager;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.ning.http.client.AsyncHttpClient;
|
||||
import java.io.File;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Collection;
|
||||
@@ -12,9 +11,9 @@ import lombok.Getter;
|
||||
import net.md_5.bungee.api.config.ConfigurationAdapter;
|
||||
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.plugin.Plugin;
|
||||
import net.md_5.bungee.api.scheduler.TaskScheduler;
|
||||
import net.md_5.bungee.api.tab.CustomTabList;
|
||||
|
||||
public abstract class ProxyServer
|
||||
{
|
||||
@@ -49,6 +48,13 @@ public abstract class ProxyServer
|
||||
*/
|
||||
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
|
||||
* {@link System#out} and {@link System#err}.
|
||||
@@ -72,20 +78,6 @@ public abstract class ProxyServer
|
||||
*/
|
||||
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
|
||||
* methods in {@link ConfigurationAdapter#getServers()}, this will not
|
||||
@@ -127,21 +119,6 @@ public abstract class ProxyServer
|
||||
*/
|
||||
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.
|
||||
*
|
||||
@@ -211,10 +188,11 @@ public abstract class ProxyServer
|
||||
*
|
||||
* @param name name of the server
|
||||
* @param address connectable Minecraft address + port of the server
|
||||
* @param motd the motd when used as a forced server
|
||||
* @param restricted whether the server info restricted property will be set
|
||||
* @return the constructed instance
|
||||
*/
|
||||
public abstract ServerInfo constructServerInfo(String name, InetSocketAddress address, boolean restricted);
|
||||
public abstract ServerInfo constructServerInfo(String name, InetSocketAddress address, String motd, boolean restricted);
|
||||
|
||||
/**
|
||||
* Returns the console overlord for this proxy. Being the console, this
|
||||
@@ -240,11 +218,33 @@ public abstract class ProxyServer
|
||||
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.
|
||||
* 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 server's {@link AsyncHttpClient} instance
|
||||
* @return the current number of connected players
|
||||
*/
|
||||
public abstract AsyncHttpClient getHttpClient();
|
||||
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);
|
||||
|
||||
/**
|
||||
* Gets the commands which are disabled and will not be run on this proxy.
|
||||
*
|
||||
* @return the set of disabled commands
|
||||
*/
|
||||
public abstract Collection<String> getDisabledCommands();
|
||||
}
|
||||
|
@@ -12,7 +12,7 @@ public interface ReconnectHandler
|
||||
* @param player the connecting player
|
||||
* @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
|
||||
@@ -20,12 +20,20 @@ public interface ReconnectHandler
|
||||
*
|
||||
* @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
|
||||
* connections, this method will be called at a predefined interval to allow
|
||||
* 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();
|
||||
}
|
||||
|
@@ -43,6 +43,15 @@ public interface ConfigurationAdapter
|
||||
*/
|
||||
public boolean getBoolean(String path, boolean def);
|
||||
|
||||
/**
|
||||
* Get a list from the specified path.
|
||||
*
|
||||
* @param path the path to retrieve the list form.
|
||||
* @param def the default value
|
||||
* @return the retrieved list
|
||||
*/
|
||||
public Collection<?> getList(String path, Collection<?> def);
|
||||
|
||||
/**
|
||||
* Get the configuration all servers which may be accessible via the proxy.
|
||||
*
|
||||
|
@@ -3,6 +3,7 @@ package net.md_5.bungee.api.config;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Map;
|
||||
import lombok.Data;
|
||||
import net.md_5.bungee.api.tab.TabListHandler;
|
||||
|
||||
/**
|
||||
* Class representing the configuration of a server listener. Used for allowing
|
||||
@@ -48,8 +49,16 @@ public class ListenerInfo
|
||||
*/
|
||||
private final Map<String, String> forcedHosts;
|
||||
/**
|
||||
* Get the texture pack used for servers connected to this proxy. May be
|
||||
* null.
|
||||
* Class used to build tab lists for this player.
|
||||
*/
|
||||
private final TexturePackInfo texturePack;
|
||||
private final Class<? extends TabListHandler> tabList;
|
||||
/**
|
||||
* Whether to set the local address when connecting to servers.
|
||||
*/
|
||||
private final boolean setLocalAddress;
|
||||
/**
|
||||
* Whether to pass the ping through when we can reliably get the target
|
||||
* server (force default server).
|
||||
*/
|
||||
private final boolean pingPassthrough;
|
||||
}
|
||||
|
@@ -36,6 +36,13 @@ public interface ServerInfo
|
||||
*/
|
||||
Collection<ProxiedPlayer> getPlayers();
|
||||
|
||||
/**
|
||||
* Returns the MOTD which should be used when this server is a forced host.
|
||||
*
|
||||
* @return the motd
|
||||
*/
|
||||
String getMotd();
|
||||
|
||||
/**
|
||||
* Whether the player can access this server. It will only return false when
|
||||
* the player has no permission and this server is restricted.
|
||||
|
@@ -1,17 +0,0 @@
|
||||
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;
|
||||
|
||||
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.
|
||||
@@ -15,7 +16,7 @@ public interface Connection
|
||||
*
|
||||
* @return the remote address
|
||||
*/
|
||||
public InetSocketAddress getAddress();
|
||||
InetSocketAddress getAddress();
|
||||
|
||||
/**
|
||||
* Disconnects this end of the connection for the specified reason. If this
|
||||
@@ -25,5 +26,23 @@ public interface Connection
|
||||
* @param reason the reason shown to the player / sent to the server on
|
||||
* disconnect
|
||||
*/
|
||||
public void disconnect(String reason);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@@ -2,6 +2,7 @@ package net.md_5.bungee.api.connection;
|
||||
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.config.ServerInfo;
|
||||
import net.md_5.bungee.api.tab.TabListHandler;
|
||||
|
||||
/**
|
||||
* Represents a player who's connection is being connected to somewhere else,
|
||||
@@ -15,7 +16,7 @@ public interface ProxiedPlayer extends Connection, CommandSender
|
||||
*
|
||||
* @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
|
||||
@@ -23,7 +24,7 @@ public interface ProxiedPlayer extends Connection, CommandSender
|
||||
*
|
||||
* @param name the name to set
|
||||
*/
|
||||
public void setDisplayName(String name);
|
||||
void setDisplayName(String name);
|
||||
|
||||
/**
|
||||
* Connects / transfers this user to the specified connection, gracefully
|
||||
@@ -32,21 +33,21 @@ public interface ProxiedPlayer extends Connection, CommandSender
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @return the server this player is connected to
|
||||
*/
|
||||
public Server getServer();
|
||||
Server getServer();
|
||||
|
||||
/**
|
||||
* Gets the ping time between the proxy and this connection.
|
||||
*
|
||||
* @return the current ping time
|
||||
*/
|
||||
public int getPing();
|
||||
int getPing();
|
||||
|
||||
/**
|
||||
* Send a plugin message to this player.
|
||||
@@ -54,19 +55,48 @@ public interface ProxiedPlayer extends Connection, CommandSender
|
||||
* @param channel the channel to send this data via
|
||||
* @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.
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
public void chat(String message);
|
||||
void chat(String message);
|
||||
|
||||
/**
|
||||
* 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();
|
||||
|
||||
/**
|
||||
* Get the server which this player will be sent to next time the log in.
|
||||
*
|
||||
* @return the server, or null if default
|
||||
*/
|
||||
ServerInfo getReconnectServer();
|
||||
|
||||
/**
|
||||
* Set the server which this player will be sent to next time the log in.
|
||||
*
|
||||
* @param server the server to set
|
||||
*/
|
||||
void setReconnectServer(ServerInfo server);
|
||||
}
|
||||
|
@@ -67,7 +67,7 @@ public class AsyncEvent<T> extends Event
|
||||
{
|
||||
Preconditions.checkState( intents.contains( plugin ), "Plugin %s has not registered intent for event %s", plugin, this );
|
||||
intents.remove( plugin );
|
||||
if ( latch.decrementAndGet() == 0 )
|
||||
if ( latch.decrementAndGet() == 0 && fired.get() )
|
||||
{
|
||||
done.done( (T) this, null );
|
||||
}
|
||||
|
@@ -1,18 +1,17 @@
|
||||
package net.md_5.bungee.api.event;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
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;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@ToString(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.
|
||||
*/
|
||||
private ServerInfo target;
|
||||
/**
|
||||
* Cancelled state.
|
||||
*/
|
||||
private boolean cancelled;
|
||||
|
||||
public ServerConnectEvent(ProxiedPlayer player, ServerInfo target)
|
||||
{
|
||||
this.player = player;
|
||||
this.target = target;
|
||||
}
|
||||
}
|
||||
|
@@ -33,11 +33,27 @@ public class ServerKickEvent extends Event implements Cancellable
|
||||
* Server to send player to if this event is cancelled.
|
||||
*/
|
||||
private ServerInfo cancelServer;
|
||||
/**
|
||||
* State in which the kick occured.
|
||||
*/
|
||||
private State state;
|
||||
|
||||
public enum State
|
||||
{
|
||||
|
||||
CONNECTING, CONNECTED, UNKNOWN;
|
||||
}
|
||||
|
||||
public ServerKickEvent(ProxiedPlayer player, String kickReason, ServerInfo cancelServer)
|
||||
{
|
||||
this( player, kickReason, cancelServer, State.UNKNOWN );
|
||||
}
|
||||
|
||||
public ServerKickEvent(ProxiedPlayer player, String kickReason, ServerInfo cancelServer, State state)
|
||||
{
|
||||
this.player = player;
|
||||
this.kickReason = kickReason;
|
||||
this.cancelServer = cancelServer;
|
||||
this.state = state;
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
@@ -2,6 +2,7 @@ package net.md_5.bungee.api.plugin;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.util.logging.Logger;
|
||||
import lombok.Getter;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.api.config.ConfigurationAdapter;
|
||||
@@ -19,6 +20,8 @@ public class Plugin
|
||||
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
|
||||
@@ -73,10 +76,11 @@ public class Plugin
|
||||
* @param description the description that describes this plugin
|
||||
* @param jarfile this plugins jar or container
|
||||
*/
|
||||
final void init(ProxyServer proxy, PluginDescription description, File file)
|
||||
final void init(ProxyServer proxy, PluginDescription description)
|
||||
{
|
||||
this.proxy = proxy;
|
||||
this.description = description;
|
||||
this.file = file;
|
||||
this.file = description.getFile();
|
||||
this.logger = new PluginLogger( this );
|
||||
}
|
||||
}
|
||||
|
@@ -2,13 +2,18 @@ package net.md_5.bungee.api.plugin;
|
||||
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
public class PluginClassloader extends URLClassLoader
|
||||
{
|
||||
|
||||
private static final Set<PluginClassloader> allLoaders = new HashSet<>();
|
||||
private static final Set<PluginClassloader> allLoaders = new CopyOnWriteArraySet<>();
|
||||
|
||||
static
|
||||
{
|
||||
ClassLoader.registerAsParallelCapable();
|
||||
}
|
||||
|
||||
public PluginClassloader(URL[] urls)
|
||||
{
|
||||
|
@@ -1,5 +1,6 @@
|
||||
package net.md_5.bungee.api.plugin;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import lombok.AllArgsConstructor;
|
||||
@@ -35,4 +36,8 @@ public class PluginDescription
|
||||
* Plugin hard dependencies.
|
||||
*/
|
||||
private Set<String> depends = new HashSet<>();
|
||||
/**
|
||||
* File we were loaded from.
|
||||
*/
|
||||
private File file = null;
|
||||
}
|
||||
|
@@ -0,0 +1,24 @@
|
||||
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() + "] ";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(LogRecord logRecord)
|
||||
{
|
||||
logRecord.setMessage( pluginName + logRecord.getMessage() );
|
||||
ProxyServer.getInstance().getLogger().log( logRecord );
|
||||
}
|
||||
}
|
@@ -1,15 +1,20 @@
|
||||
package net.md_5.bungee.api.plugin;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.eventbus.EventBus;
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Stack;
|
||||
import java.util.jar.JarEntry;
|
||||
@@ -20,7 +25,8 @@ import lombok.RequiredArgsConstructor;
|
||||
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.event.LoginEvent;
|
||||
import net.md_5.bungee.event.EventBus;
|
||||
import net.md_5.bungee.event.EventHandler;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
|
||||
/**
|
||||
@@ -36,9 +42,19 @@ public class PluginManager
|
||||
private final ProxyServer proxy;
|
||||
/*========================================================================*/
|
||||
private final Yaml yaml = new Yaml();
|
||||
private final EventBus eventBus = new EventBus();
|
||||
private final Map<String, Plugin> plugins = new HashMap<>();
|
||||
private final EventBus eventBus;
|
||||
private final Map<String, Plugin> plugins = new LinkedHashMap<>();
|
||||
private final Map<String, Command> commandMap = new HashMap<>();
|
||||
private Map<String, PluginDescription> toLoad = new HashMap<>();
|
||||
private Multimap<Plugin, Command> commandsByPlugin = ArrayListMultimap.create();
|
||||
private Multimap<Plugin, Listener> listenersByPlugin = ArrayListMultimap.create();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public PluginManager(ProxyServer proxy)
|
||||
{
|
||||
this.proxy = proxy;
|
||||
eventBus = new EventBus( proxy.getLogger() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a command so that it may be executed.
|
||||
@@ -53,6 +69,7 @@ public class PluginManager
|
||||
{
|
||||
commandMap.put( alias.toLowerCase(), command );
|
||||
}
|
||||
commandsByPlugin.put( plugin, command );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,6 +80,26 @@ public class PluginManager
|
||||
public void unregisterCommand(Command command)
|
||||
{
|
||||
commandMap.values().remove( command );
|
||||
commandsByPlugin.values().remove( command );
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister all commands owned by a {@link Plugin}
|
||||
*
|
||||
* @param plugin the plugin to register the commands of
|
||||
*/
|
||||
public void unregisterCommands(Plugin plugin)
|
||||
{
|
||||
for ( Iterator<Command> it = commandsByPlugin.get( plugin ).iterator(); it.hasNext(); )
|
||||
{
|
||||
commandMap.values().remove( it.next() );
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean dispatchCommand(CommandSender sender, String commandLine)
|
||||
{
|
||||
return dispatchCommand( sender, commandLine, null );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -73,10 +110,21 @@ public class PluginManager
|
||||
* arguments
|
||||
* @return whether the command was handled
|
||||
*/
|
||||
public boolean dispatchCommand(CommandSender sender, String commandLine)
|
||||
public boolean dispatchCommand(CommandSender sender, String commandLine, List<String> tabResults)
|
||||
{
|
||||
String[] split = argsSplit.split( commandLine );
|
||||
Command command = commandMap.get( split[0].toLowerCase() );
|
||||
// Check for chat that only contains " "
|
||||
if ( split.length == 0 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
String commandName = split[0].toLowerCase();
|
||||
if ( proxy.getDisabledCommands().contains( commandName ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Command command = commandMap.get( commandName );
|
||||
if ( command == null )
|
||||
{
|
||||
return false;
|
||||
@@ -85,14 +133,23 @@ public class PluginManager
|
||||
String permission = command.getPermission();
|
||||
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;
|
||||
}
|
||||
|
||||
String[] args = Arrays.copyOfRange( split, 1, split.length );
|
||||
try
|
||||
{
|
||||
if ( tabResults == null )
|
||||
{
|
||||
command.execute( sender, args );
|
||||
} else if ( command instanceof TabExecutor )
|
||||
{
|
||||
for ( String s : ( (TabExecutor) command ).onTabComplete( sender, args ) )
|
||||
{
|
||||
tabResults.add( s );
|
||||
}
|
||||
}
|
||||
} catch ( Exception ex )
|
||||
{
|
||||
sender.sendMessage( ChatColor.RED + "An internal error occurred whilst executing this command, please check the console log for details." );
|
||||
@@ -122,23 +179,37 @@ public class PluginManager
|
||||
return plugins.get( name );
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable all plugins by calling the {@link Plugin#onEnable()} method.
|
||||
*/
|
||||
public void enablePlugins()
|
||||
public void loadAndEnablePlugins()
|
||||
{
|
||||
Map<Plugin, Boolean> pluginStatuses = new HashMap<>();
|
||||
for ( Map.Entry<String, Plugin> entry : plugins.entrySet() )
|
||||
Map<PluginDescription, Boolean> pluginStatuses = new HashMap<>();
|
||||
for ( Map.Entry<String, PluginDescription> entry : toLoad.entrySet() )
|
||||
{
|
||||
Plugin plugin = entry.getValue();
|
||||
if ( !this.enablePlugin( pluginStatuses, new Stack<Plugin>(), plugin ) )
|
||||
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() )
|
||||
{
|
||||
try
|
||||
{
|
||||
plugin.onEnable();
|
||||
ProxyServer.getInstance().getLogger().log( Level.INFO, "Enabled plugin {0} version {1} by {2}", new Object[]
|
||||
{
|
||||
plugin.getDescription().getName(), plugin.getDescription().getVersion(), plugin.getDescription().getAuthor()
|
||||
} );
|
||||
} catch ( Throwable t )
|
||||
{
|
||||
ProxyServer.getInstance().getLogger().log( Level.WARNING, "Exception encountered when loading plugin: " + plugin.getDescription().getName(), t );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean enablePlugin(Map<Plugin, Boolean> pluginStatuses, Stack<Plugin> dependStack, Plugin plugin)
|
||||
private boolean enablePlugin(Map<PluginDescription, Boolean> pluginStatuses, Stack<PluginDescription> dependStack, PluginDescription plugin)
|
||||
{
|
||||
if ( pluginStatuses.containsKey( plugin ) )
|
||||
{
|
||||
@@ -149,21 +220,21 @@ public class PluginManager
|
||||
boolean status = true;
|
||||
|
||||
// try to load dependencies first
|
||||
for ( String dependName : plugin.getDescription().getDepends() )
|
||||
for ( String dependName : plugin.getDepends() )
|
||||
{
|
||||
Plugin depend = this.plugins.get( dependName );
|
||||
Boolean dependStatus = depend != null ? pluginStatuses.get( depend ) : Boolean.FALSE;
|
||||
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 ( Plugin element : dependStack )
|
||||
for ( PluginDescription element : dependStack )
|
||||
{
|
||||
dependencyGraph.append( element.getDescription().getName() ).append( " -> " );
|
||||
dependencyGraph.append( element.getName() ).append( " -> " );
|
||||
}
|
||||
dependencyGraph.append( plugin.getDescription().getName() ).append( " -> " ).append( dependName );
|
||||
dependencyGraph.append( plugin.getName() ).append( " -> " ).append( dependName );
|
||||
ProxyServer.getInstance().getLogger().log( Level.WARNING, "Circular dependency detected: " + dependencyGraph );
|
||||
status = false;
|
||||
} else
|
||||
@@ -178,7 +249,7 @@ public class PluginManager
|
||||
{
|
||||
ProxyServer.getInstance().getLogger().log( Level.WARNING, "{0} (required by {1}) is unavailable", new Object[]
|
||||
{
|
||||
depend.getDescription().getName(), plugin.getDescription().getName()
|
||||
String.valueOf( depend.getName() ), plugin.getName()
|
||||
} );
|
||||
status = false;
|
||||
}
|
||||
@@ -194,15 +265,23 @@ public class PluginManager
|
||||
{
|
||||
try
|
||||
{
|
||||
plugin.onEnable();
|
||||
ProxyServer.getInstance().getLogger().log( Level.INFO, "Enabled plugin {0} version {1} by {2}", new Object[]
|
||||
URLClassLoader loader = new PluginClassloader( new URL[]
|
||||
{
|
||||
plugin.getDescription().getName(), plugin.getDescription().getVersion(), plugin.getDescription().getAuthor()
|
||||
plugin.getFile().toURI().toURL()
|
||||
} );
|
||||
Class<?> main = loader.loadClass( plugin.getMain() );
|
||||
Plugin clazz = (Plugin) main.getDeclaredConstructor().newInstance();
|
||||
|
||||
clazz.init( proxy, plugin );
|
||||
plugins.put( plugin.getName(), clazz );
|
||||
clazz.onLoad();
|
||||
ProxyServer.getInstance().getLogger().log( Level.INFO, "Loaded plugin {0} version {1} by {2}", new Object[]
|
||||
{
|
||||
plugin.getName(), plugin.getVersion(), plugin.getAuthor()
|
||||
} );
|
||||
} catch ( Throwable t )
|
||||
{
|
||||
ProxyServer.getInstance().getLogger().log( Level.WARNING, "Exception encountered when loading plugin: " + plugin.getDescription().getName(), t );
|
||||
status = false;
|
||||
proxy.getLogger().log( Level.WARNING, "Error enabling plugin " + plugin.getName(), t );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,51 +289,12 @@ public class PluginManager
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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" );
|
||||
Preconditions.checkArgument( file.isFile(), "Must load from file" );
|
||||
|
||||
try ( JarFile jar = new JarFile( 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 );
|
||||
URLClassLoader loader = new PluginClassloader( new URL[]
|
||||
{
|
||||
file.toURI().toURL()
|
||||
} );
|
||||
Class<?> main = loader.loadClass( desc.getMain() );
|
||||
Plugin plugin = (Plugin) main.getDeclaredConstructor().newInstance();
|
||||
|
||||
plugin.init( proxy, desc, file );
|
||||
plugins.put( desc.getName(), plugin );
|
||||
plugin.onLoad();
|
||||
ProxyServer.getInstance().getLogger().log( Level.INFO, "Loaded plugin {0} version {1} by {2}", new Object[]
|
||||
{
|
||||
desc.getName(), desc.getVersion(), desc.getAuthor()
|
||||
} );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load all plugins from the specified folder.
|
||||
*
|
||||
* @param folder the folder to search for plugins in
|
||||
*/
|
||||
public void loadPlugins(File folder)
|
||||
public void detectPlugins(File folder)
|
||||
{
|
||||
Preconditions.checkNotNull( folder, "folder" );
|
||||
Preconditions.checkArgument( folder.isDirectory(), "Must load from a directory" );
|
||||
@@ -263,9 +303,17 @@ public class PluginManager
|
||||
{
|
||||
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 )
|
||||
{
|
||||
ProxyServer.getInstance().getLogger().log( Level.WARNING, "Could not load plugin from file " + file, ex );
|
||||
@@ -304,13 +352,44 @@ public class PluginManager
|
||||
/**
|
||||
* Register a {@link Listener} for receiving called events. Methods in this
|
||||
* Object which wish to receive events must be annotated with the
|
||||
* {@link Subscribe} annotation.
|
||||
* {@link EventHandler} annotation.
|
||||
*
|
||||
* @param plugin the owning plugin
|
||||
* @param listener the listener to register events for
|
||||
*/
|
||||
public void registerListener(Plugin plugin, Listener listener)
|
||||
{
|
||||
for ( Method method : listener.getClass().getDeclaredMethods() )
|
||||
{
|
||||
Preconditions.checkArgument( !method.isAnnotationPresent( Subscribe.class ),
|
||||
"Listener %s has registered using deprecated subscribe annotation! Please update to @EventHandler.", listener );
|
||||
}
|
||||
eventBus.register( listener );
|
||||
listenersByPlugin.put( plugin, listener );
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister a {@link Listener} so that the events do not reach it anymore.
|
||||
*
|
||||
* @param listener the listener to unregister
|
||||
*/
|
||||
public void unregisterListener(Listener listener)
|
||||
{
|
||||
eventBus.unregister( listener );
|
||||
listenersByPlugin.values().remove( listener );
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister all of a Plugin's listener.
|
||||
*
|
||||
* @param plugin
|
||||
*/
|
||||
public void unregisterListeners(Plugin plugin)
|
||||
{
|
||||
for ( Iterator<Listener> it = listenersByPlugin.get( plugin ).iterator(); it.hasNext(); )
|
||||
{
|
||||
eventBus.unregister( it.next() );
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,10 @@
|
||||
package net.md_5.bungee.api.plugin;
|
||||
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
|
||||
|
||||
public interface TabExecutor
|
||||
{
|
||||
|
||||
public Iterable<String> onTabComplete(CommandSender sender, String[] args);
|
||||
}
|
@@ -1,6 +1,5 @@
|
||||
package net.md_5.bungee.api.scheduler;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import net.md_5.bungee.api.plugin.Plugin;
|
||||
|
||||
/**
|
||||
@@ -31,11 +30,7 @@ public interface ScheduledTask
|
||||
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
|
||||
* Cancel this task to suppress subsequent executions.
|
||||
*/
|
||||
long getDelay(TimeUnit unit);
|
||||
void cancel();
|
||||
}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
package net.md_5.bungee.api.scoreboard;
|
||||
package net.md_5.bungee.api.score;
|
||||
|
||||
import lombok.Data;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
package net.md_5.bungee.api.scoreboard;
|
||||
package net.md_5.bungee.api.score;
|
||||
|
||||
/**
|
||||
* Represents locations for a scoreboard to be displayed.
|
@@ -1,4 +1,4 @@
|
||||
package net.md_5.bungee.api.scoreboard;
|
||||
package net.md_5.bungee.api.score;
|
||||
|
||||
import lombok.Data;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
package net.md_5.bungee.api.scoreboard;
|
||||
package net.md_5.bungee.api.score;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import java.util.Collection;
|
||||
@@ -59,7 +59,6 @@ public class Scoreboard
|
||||
public void addScore(Score score)
|
||||
{
|
||||
Preconditions.checkNotNull( score, "score" );
|
||||
Preconditions.checkArgument( !scores.containsKey( score.getItemName() ), "Score %s already exists in this scoreboard", score.getItemName() );
|
||||
scores.put( score.getItemName(), score );
|
||||
}
|
||||
|
@@ -1,20 +1,22 @@
|
||||
package net.md_5.bungee.api.scoreboard;
|
||||
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 byte friendlyMode;
|
||||
private boolean friendlyFire;
|
||||
private Set<String> players = new HashSet<>();
|
||||
|
||||
public Collection<String> getPlayers()
|
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;
|
||||
|
||||
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.
|
||||
*
|
||||
* @param player the connecting player
|
||||
*/
|
||||
public void onConnect(ProxiedPlayer player);
|
||||
|
||||
/**
|
||||
* Called when a player changes their connected server.
|
||||
*
|
||||
* @param player the player who changed servers
|
||||
*/
|
||||
public void onServerChange(ProxiedPlayer player);
|
||||
void onServerChange();
|
||||
|
||||
/**
|
||||
* 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 ping the player's new ping.
|
||||
*/
|
||||
public void onPingChange(ProxiedPlayer player, int ping);
|
||||
void onPingChange(int ping);
|
||||
|
||||
/**
|
||||
* Called when a player disconnects.
|
||||
*
|
||||
* @param player the disconnected player
|
||||
*/
|
||||
public void onDisconnect(ProxiedPlayer player);
|
||||
void onDisconnect();
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @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>
|
@@ -6,13 +6,13 @@
|
||||
<parent>
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-parent</artifactId>
|
||||
<version>1.4.7-SNAPSHOT</version>
|
||||
<version>1.6.2-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-config</artifactId>
|
||||
<version>1.4.7-SNAPSHOT</version>
|
||||
<version>1.6.2-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>BungeeCord-Config</name>
|
||||
|
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>
|
20
event/pom.xml
Normal file
20
event/pom.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
|
||||
<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.6.2-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-event</artifactId>
|
||||
<version>1.6.2-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>BungeeCord-Event</name>
|
||||
<description>Generic java event dispatching API intended for use with BungeeCord</description>
|
||||
</project>
|
202
event/src/main/java/net/md_5/bungee/event/EventBus.java
Normal file
202
event/src/main/java/net/md_5/bungee/event/EventBus.java
Normal file
@@ -0,0 +1,202 @@
|
||||
package net.md_5.bungee.event;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
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<Byte, Map<Object, Method[]>>> byListenerAndPriority = new HashMap<>();
|
||||
private final Map<Class<?>, EventHandlerMethod[]> byEventBaked = new HashMap<>();
|
||||
private final ReadWriteLock lock = new ReentrantReadWriteLock();
|
||||
private final Logger logger;
|
||||
|
||||
public EventBus()
|
||||
{
|
||||
this( null );
|
||||
}
|
||||
|
||||
public EventBus(Logger logger)
|
||||
{
|
||||
this.logger = ( logger == null ) ? Logger.getGlobal() : logger;
|
||||
}
|
||||
|
||||
public void post(Object event)
|
||||
{
|
||||
lock.readLock().lock();
|
||||
try
|
||||
{
|
||||
EventHandlerMethod[] handlers = byEventBaked.get( event.getClass() );
|
||||
if ( handlers != null )
|
||||
{
|
||||
for ( EventHandlerMethod method : handlers )
|
||||
{
|
||||
try
|
||||
{
|
||||
method.invoke( 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, method.getListener() ), ex.getCause() );
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally
|
||||
{
|
||||
lock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private Map<Class<?>, Map<Byte, Set<Method>>> findHandlers(Object listener)
|
||||
{
|
||||
Map<Class<?>, Map<Byte, Set<Method>>> handler = new HashMap<>();
|
||||
for ( Method m : listener.getClass().getDeclaredMethods() )
|
||||
{
|
||||
EventHandler annotation = m.getAnnotation( EventHandler.class );
|
||||
if ( annotation != null )
|
||||
{
|
||||
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;
|
||||
}
|
||||
Map<Byte, Set<Method>> prioritiesMap = handler.get( params[0] );
|
||||
if ( prioritiesMap == null )
|
||||
{
|
||||
prioritiesMap = new HashMap<>();
|
||||
handler.put( params[0], prioritiesMap );
|
||||
}
|
||||
Set<Method> priority = prioritiesMap.get( annotation.priority() );
|
||||
if ( priority == null )
|
||||
{
|
||||
priority = new HashSet<>();
|
||||
prioritiesMap.put( annotation.priority(), priority );
|
||||
}
|
||||
priority.add( m );
|
||||
}
|
||||
}
|
||||
return handler;
|
||||
}
|
||||
|
||||
public void register(Object listener)
|
||||
{
|
||||
Map<Class<?>, Map<Byte, Set<Method>>> handler = findHandlers( listener );
|
||||
lock.writeLock().lock();
|
||||
try
|
||||
{
|
||||
for ( Map.Entry<Class<?>, Map<Byte, Set<Method>>> e : handler.entrySet() )
|
||||
{
|
||||
Map<Byte, Map<Object, Method[]>> prioritiesMap = byListenerAndPriority.get( e.getKey() );
|
||||
if ( prioritiesMap == null )
|
||||
{
|
||||
prioritiesMap = new HashMap<>();
|
||||
byListenerAndPriority.put( e.getKey(), prioritiesMap );
|
||||
}
|
||||
for ( Map.Entry<Byte, Set<Method>> entry : e.getValue().entrySet() )
|
||||
{
|
||||
Map<Object, Method[]> currentPriorityMap = prioritiesMap.get( entry.getKey() );
|
||||
if ( currentPriorityMap == null )
|
||||
{
|
||||
currentPriorityMap = new HashMap<>();
|
||||
prioritiesMap.put( entry.getKey(), currentPriorityMap );
|
||||
}
|
||||
Method[] baked = new Method[ entry.getValue().size() ];
|
||||
currentPriorityMap.put( listener, entry.getValue().toArray( baked ) );
|
||||
}
|
||||
bakeHandlers( e.getKey() );
|
||||
}
|
||||
} finally
|
||||
{
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void unregister(Object listener)
|
||||
{
|
||||
Map<Class<?>, Map<Byte, Set<Method>>> handler = findHandlers( listener );
|
||||
lock.writeLock().lock();
|
||||
try
|
||||
{
|
||||
for ( Map.Entry<Class<?>, Map<Byte, Set<Method>>> e : handler.entrySet() )
|
||||
{
|
||||
Map<Byte, Map<Object, Method[]>> prioritiesMap = byListenerAndPriority.get( e.getKey() );
|
||||
if ( prioritiesMap != null )
|
||||
{
|
||||
for ( Byte priority : e.getValue().keySet() )
|
||||
{
|
||||
Map<Object, Method[]> currentPriority = prioritiesMap.get( priority );
|
||||
if ( currentPriority != null )
|
||||
{
|
||||
currentPriority.remove( listener );
|
||||
if ( currentPriority.isEmpty() )
|
||||
{
|
||||
prioritiesMap.remove( priority );
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( prioritiesMap.isEmpty() )
|
||||
{
|
||||
byListenerAndPriority.remove( e.getKey() );
|
||||
}
|
||||
}
|
||||
bakeHandlers( e.getKey() );
|
||||
}
|
||||
} finally
|
||||
{
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shouldn't be called without first locking the writeLock; intended for use
|
||||
* only inside {@link #register(java.lang.Object) register(Object)} or
|
||||
* {@link #unregister(java.lang.Object) unregister(Object)}.
|
||||
*/
|
||||
private void bakeHandlers(Class<?> eventClass)
|
||||
{
|
||||
Map<Byte, Map<Object, Method[]>> handlersByPriority = byListenerAndPriority.get( eventClass );
|
||||
if ( handlersByPriority != null )
|
||||
{
|
||||
List<EventHandlerMethod> handlersList = new ArrayList<>( handlersByPriority.size() * 2 );
|
||||
for ( byte value = Byte.MIN_VALUE; value < Byte.MAX_VALUE; value++ )
|
||||
{
|
||||
Map<Object, Method[]> handlersByListener = handlersByPriority.get( value );
|
||||
if ( handlersByListener != null )
|
||||
{
|
||||
for ( Map.Entry<Object, Method[]> listenerHandlers : handlersByListener.entrySet() )
|
||||
{
|
||||
for ( Method method : listenerHandlers.getValue() )
|
||||
{
|
||||
EventHandlerMethod ehm = new EventHandlerMethod( listenerHandlers.getKey(), method );
|
||||
handlersList.add( ehm );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
byEventBaked.put( eventClass, handlersList.toArray( new EventHandlerMethod[ handlersList.size() ] ) );
|
||||
} else
|
||||
{
|
||||
byEventBaked.put( eventClass, null );
|
||||
}
|
||||
}
|
||||
}
|
26
event/src/main/java/net/md_5/bungee/event/EventHandler.java
Normal file
26
event/src/main/java/net/md_5/bungee/event/EventHandler.java
Normal file
@@ -0,0 +1,26 @@
|
||||
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
|
||||
{
|
||||
|
||||
/**
|
||||
* Define the priority of the event handler.
|
||||
* <p>
|
||||
* Event handlers are called in order of priority:
|
||||
* <ol>
|
||||
* <li>LOWEST</li>
|
||||
* <li>LOW</li>
|
||||
* <li>NORMAL</li>
|
||||
* <li>HIGH</li>
|
||||
* <li>HIGHEST</li>
|
||||
* </ol>
|
||||
*/
|
||||
byte priority() default EventPriority.NORMAL;
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
package net.md_5.bungee.event;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
@AllArgsConstructor
|
||||
public class EventHandlerMethod
|
||||
{
|
||||
|
||||
@Getter
|
||||
private final Object listener;
|
||||
@Getter
|
||||
private final Method method;
|
||||
|
||||
public void invoke(Object event) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException
|
||||
{
|
||||
method.invoke( listener, event );
|
||||
}
|
||||
}
|
19
event/src/main/java/net/md_5/bungee/event/EventPriority.java
Normal file
19
event/src/main/java/net/md_5/bungee/event/EventPriority.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package net.md_5.bungee.event;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* Importance of the {@link EventHandler}. When executing an Event, the handlers
|
||||
* are called in order of their Priority.
|
||||
*/
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class EventPriority
|
||||
{
|
||||
|
||||
public static final byte LOWEST = -64;
|
||||
public static final byte LOW = -32;
|
||||
public static final byte NORMAL = 0;
|
||||
public static final byte HIGH = 32;
|
||||
public static final byte HIGHEST = 64;
|
||||
}
|
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( 0, latch.getCount() );
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void firstListener(FirstEvent event)
|
||||
{
|
||||
bus.post( new SecondEvent() );
|
||||
Assert.assertEquals( 1, latch.getCount() );
|
||||
latch.countDown();
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void secondListener(SecondEvent event)
|
||||
{
|
||||
latch.countDown();
|
||||
}
|
||||
|
||||
public static class FirstEvent
|
||||
{
|
||||
}
|
||||
|
||||
public static class SecondEvent
|
||||
{
|
||||
}
|
||||
}
|
@@ -0,0 +1,64 @@
|
||||
package net.md_5.bungee.event;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class EventPriorityTest
|
||||
{
|
||||
|
||||
private final EventBus bus = new EventBus();
|
||||
private final CountDownLatch latch = new CountDownLatch( 5 );
|
||||
|
||||
@Test
|
||||
public void testPriority()
|
||||
{
|
||||
bus.register( this );
|
||||
bus.register( new EventPriorityListenerPartner() );
|
||||
bus.post( new PriorityTestEvent() );
|
||||
Assert.assertEquals( 0, latch.getCount() );
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onLowestPriority(PriorityTestEvent event)
|
||||
{
|
||||
Assert.assertEquals( 5, latch.getCount() );
|
||||
latch.countDown();
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onNormalPriority(PriorityTestEvent event)
|
||||
{
|
||||
Assert.assertEquals( 3, latch.getCount() );
|
||||
latch.countDown();
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onHighestPriority(PriorityTestEvent event)
|
||||
{
|
||||
Assert.assertEquals( 1, latch.getCount() );
|
||||
latch.countDown();
|
||||
}
|
||||
|
||||
public static class PriorityTestEvent
|
||||
{
|
||||
}
|
||||
|
||||
public class EventPriorityListenerPartner
|
||||
{
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH)
|
||||
public void onHighPriority(PriorityTestEvent event)
|
||||
{
|
||||
Assert.assertEquals( 2, latch.getCount() );
|
||||
latch.countDown();
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW)
|
||||
public void onLowPriority(PriorityTestEvent event)
|
||||
{
|
||||
Assert.assertEquals( 4, latch.getCount() );
|
||||
latch.countDown();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,28 @@
|
||||
package net.md_5.bungee.event;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class UnregisteringListenerTest
|
||||
{
|
||||
|
||||
private final EventBus bus = new EventBus();
|
||||
|
||||
@Test
|
||||
public void testPriority()
|
||||
{
|
||||
bus.register( this );
|
||||
bus.unregister( this );
|
||||
bus.post( new TestEvent() );
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onEvent(TestEvent evt)
|
||||
{
|
||||
Assert.fail( "Event listener wasn't unregistered" );
|
||||
}
|
||||
|
||||
public static class TestEvent
|
||||
{
|
||||
}
|
||||
}
|
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>
|
25
pom.xml
25
pom.xml
@@ -11,16 +11,16 @@
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-parent</artifactId>
|
||||
<version>1.5-SNAPSHOT</version>
|
||||
<version>1.6.2-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>BungeeCord</name>
|
||||
<description>Parent project for all BungeeCord modules.</description>
|
||||
<url>https://github.com/ElasticPortalSuite/BungeeCord</url>
|
||||
<url>https://github.com/SpigotMC/BungeeCord</url>
|
||||
<inceptionYear>2012</inceptionYear>
|
||||
<organization>
|
||||
<name>Elastic Portal Suite</name>
|
||||
<url>https://github.com/ElasticPortalSuite</url>
|
||||
<url>https://github.com/SpigotMC</url>
|
||||
</organization>
|
||||
<licenses>
|
||||
<license>
|
||||
@@ -38,18 +38,19 @@
|
||||
|
||||
<modules>
|
||||
<module>api</module>
|
||||
<module>event</module>
|
||||
<module>protocol</module>
|
||||
<module>proxy</module>
|
||||
</modules>
|
||||
|
||||
<scm>
|
||||
<connection>scm:git:git@github.com:ElasticPortalSuite/BungeeCord.git</connection>
|
||||
<developerConnection>scm:git:git@github.com:ElasticPortalSuite/BungeeCord.git</developerConnection>
|
||||
<url>git@github.com:ElasticPortalSuite/BungeeCord.git</url>
|
||||
<connection>scm:git:git@github.com:SpigotMC/BungeeCord.git</connection>
|
||||
<developerConnection>scm:git:git@github.com:SpigotMC/BungeeCord.git</developerConnection>
|
||||
<url>git@github.com:SpigotMC/BungeeCord.git</url>
|
||||
</scm>
|
||||
<issueManagement>
|
||||
<system>GitHub</system>
|
||||
<url>https://github.com/ElasticPortalSuite/BungeeCord/issues</url>
|
||||
<url>https://github.com/SpigotMC/BungeeCord/issues</url>
|
||||
</issueManagement>
|
||||
<ciManagement>
|
||||
<system>jenkins</system>
|
||||
@@ -58,15 +59,21 @@
|
||||
|
||||
<properties>
|
||||
<build.number>unknown</build.number>
|
||||
<netty.version>4.0.0.CR1</netty.version>
|
||||
<netty.version>4.0.9.Final</netty.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.11</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>0.11.8</version>
|
||||
<version>0.12.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
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,13 +6,13 @@
|
||||
<parent>
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-parent</artifactId>
|
||||
<version>1.5-SNAPSHOT</version>
|
||||
<version>1.6.2-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-protocol</artifactId>
|
||||
<version>1.5-SNAPSHOT</version>
|
||||
<version>1.6.2-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>BungeeCord-Protocol</name>
|
||||
@@ -23,7 +23,7 @@
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-buffer</artifactId>
|
||||
<version>${netty.version}</version>
|
||||
<scope>provided</scope>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</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,38 @@
|
||||
package net.md_5.bungee.protocol;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class MinecraftInput
|
||||
{
|
||||
|
||||
private final ByteBuf buf;
|
||||
|
||||
public byte readByte()
|
||||
{
|
||||
return buf.readByte();
|
||||
}
|
||||
|
||||
public short readUnisgnedByte()
|
||||
{
|
||||
return buf.readUnsignedByte();
|
||||
}
|
||||
|
||||
public int readInt()
|
||||
{
|
||||
return buf.readInt();
|
||||
}
|
||||
|
||||
public String readString()
|
||||
{
|
||||
short len = buf.readShort();
|
||||
char[] c = new char[ len ];
|
||||
for ( int i = 0; i < c.length; i++ )
|
||||
{
|
||||
c[i] = buf.readChar();
|
||||
}
|
||||
|
||||
return new String( c );
|
||||
}
|
||||
}
|
@@ -0,0 +1,56 @@
|
||||
package net.md_5.bungee.protocol;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class MinecraftOutput
|
||||
{
|
||||
|
||||
private final ByteBuf buf;
|
||||
|
||||
public MinecraftOutput()
|
||||
{
|
||||
buf = Unpooled.buffer();
|
||||
}
|
||||
|
||||
public byte[] toArray()
|
||||
{
|
||||
if ( buf.hasArray() )
|
||||
{
|
||||
return Arrays.copyOfRange( buf.array(), buf.arrayOffset(), buf.arrayOffset() + buf.writerIndex() );
|
||||
} else
|
||||
{
|
||||
byte[] b = new byte[ buf.writerIndex() ];
|
||||
buf.readBytes( b );
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
public MinecraftOutput writeByte(byte b)
|
||||
{
|
||||
buf.writeByte( b );
|
||||
return this;
|
||||
}
|
||||
|
||||
public void writeInt(int i)
|
||||
{
|
||||
buf.writeInt( i );
|
||||
}
|
||||
|
||||
public void writeString(String s)
|
||||
{
|
||||
char[] cc = s.toCharArray();
|
||||
buf.writeShort( cc.length );
|
||||
for ( char c : cc )
|
||||
{
|
||||
buf.writeChar( c );
|
||||
}
|
||||
}
|
||||
|
||||
public void writeStringUTF8WithoutLengthHeaderBecauseDinnerboneStuffedUpTheMCBrandPacket(String s)
|
||||
{
|
||||
buf.writeBytes( s.getBytes( Charset.forName( "UTF-8" ) ) );
|
||||
}
|
||||
}
|
@@ -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, OPTIONAL_WINDOW
|
||||
}
|
@@ -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,38 +1,131 @@
|
||||
package net.md_5.bungee.protocol;
|
||||
|
||||
import static net.md_5.bungee.protocol.PacketDefinitions.OpCode.*;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
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.Packet2CEntityProperties;
|
||||
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.PacketCBTabComplete;
|
||||
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
|
||||
{
|
||||
|
||||
public static final OpCode[][] opCodes = new OpCode[ 512 ][];
|
||||
public static final int VANILLA_PROTOCOL = 0;
|
||||
public static final int FORGE_PROTOCOL = 256;
|
||||
public static final byte PROTOCOL_VERSION = 74;
|
||||
public static final String GAME_VERSION = "1.6.2";
|
||||
@Getter
|
||||
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()
|
||||
{
|
||||
|
||||
BOOLEAN, BULK_CHUNK, BYTE, BYTE_INT, DOUBLE, FLOAT, INT, INT_3, INT_BYTE, ITEM, LONG, METADATA, OPTIONAL_MOTION, SCORE, SHORT, SHORT_BYTE, SHORT_ITEM, STRING, TEAM, USHORT_BYTE
|
||||
classes[0x00] = Packet0KeepAlive.class;
|
||||
classes[0x01] = Packet1Login.class;
|
||||
classes[0x02] = Packet2Handshake.class;
|
||||
classes[0x03] = Packet3Chat.class;
|
||||
classes[0x09] = Packet9Respawn.class;
|
||||
classes[0xC9] = PacketC9PlayerListItem.class;
|
||||
classes[0x2C] = Packet2CEntityProperties.class;
|
||||
classes[0xCC] = PacketCCSettings.class;
|
||||
classes[0xCB] = PacketCBTabComplete.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
|
||||
};
|
||||
opCodes[0x01] = new OpCode[]
|
||||
throw new RuntimeException( "Unknown packet id " + packetId );
|
||||
}
|
||||
return packet;
|
||||
}
|
||||
|
||||
public static DefinedPacket read(short id, ByteBuf buf, Protocol protocol)
|
||||
{
|
||||
INT, STRING, BYTE, BYTE, BYTE, BYTE, BYTE
|
||||
};
|
||||
opCodes[0x02] = new OpCode[]
|
||||
DefinedPacket packet = packet( id, protocol );
|
||||
if ( packet != null )
|
||||
{
|
||||
BYTE, STRING, STRING, INT
|
||||
};
|
||||
opCodes[0x03] = new OpCode[]
|
||||
packet.read( buf );
|
||||
return packet;
|
||||
}
|
||||
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[]
|
||||
{
|
||||
LONG, LONG
|
||||
@@ -51,11 +144,7 @@ public class PacketDefinitions
|
||||
};
|
||||
opCodes[0x08] = new OpCode[]
|
||||
{
|
||||
SHORT, SHORT, FLOAT
|
||||
};
|
||||
opCodes[0x09] = new OpCode[]
|
||||
{
|
||||
INT, BYTE, BYTE, SHORT, STRING
|
||||
FLOAT, SHORT, FLOAT
|
||||
};
|
||||
opCodes[0x0A] = new OpCode[]
|
||||
{
|
||||
@@ -95,7 +184,7 @@ public class PacketDefinitions
|
||||
};
|
||||
opCodes[0x13] = new OpCode[]
|
||||
{
|
||||
INT, BYTE
|
||||
INT, BYTE, INT
|
||||
};
|
||||
opCodes[0x14] = new OpCode[]
|
||||
{
|
||||
@@ -121,6 +210,10 @@ public class PacketDefinitions
|
||||
{
|
||||
INT, INT, INT, INT, SHORT
|
||||
};
|
||||
opCodes[0x1B] = new OpCode[]
|
||||
{
|
||||
FLOAT, FLOAT, BOOLEAN, BOOLEAN
|
||||
};
|
||||
opCodes[0x1C] = new OpCode[]
|
||||
{
|
||||
INT, SHORT, SHORT, SHORT
|
||||
@@ -159,7 +252,7 @@ public class PacketDefinitions
|
||||
};
|
||||
opCodes[0x27] = new OpCode[]
|
||||
{
|
||||
INT, INT
|
||||
INT, INT, BOOLEAN
|
||||
};
|
||||
opCodes[0x28] = new OpCode[]
|
||||
{
|
||||
@@ -227,7 +320,7 @@ public class PacketDefinitions
|
||||
};
|
||||
opCodes[0x64] = new OpCode[]
|
||||
{
|
||||
BYTE, BYTE, STRING, BYTE, BOOLEAN
|
||||
OPTIONAL_WINDOW
|
||||
};
|
||||
opCodes[0x65] = new OpCode[]
|
||||
{
|
||||
@@ -273,74 +366,25 @@ public class PacketDefinitions
|
||||
{
|
||||
INT, SHORT, INT, BYTE, SHORT_BYTE
|
||||
};
|
||||
opCodes[0x85] = new OpCode[]
|
||||
{
|
||||
BYTE, INT, INT, INT
|
||||
};
|
||||
opCodes[0xC3] = new OpCode[]
|
||||
{
|
||||
SHORT, SHORT, INT_BYTE
|
||||
};
|
||||
opCodes[0xC8] = new OpCode[]
|
||||
{
|
||||
INT, BYTE
|
||||
};
|
||||
opCodes[0xC9] = new OpCode[]
|
||||
{
|
||||
STRING, BOOLEAN, SHORT
|
||||
INT, INT
|
||||
};
|
||||
opCodes[0xCA] = new OpCode[]
|
||||
{
|
||||
BYTE, BYTE, BYTE
|
||||
BYTE, FLOAT, FLOAT
|
||||
};
|
||||
opCodes[0xCB] = new OpCode[]
|
||||
{
|
||||
STRING
|
||||
};
|
||||
opCodes[0xCC] = new OpCode[]
|
||||
{
|
||||
STRING, BYTE, BYTE, BYTE, BOOLEAN
|
||||
};
|
||||
opCodes[0xCD] = new OpCode[]
|
||||
{
|
||||
BYTE
|
||||
};
|
||||
opCodes[0xCE] = new OpCode[]
|
||||
{
|
||||
STRING, STRING, BYTE
|
||||
};
|
||||
opCodes[0xCF] = new OpCode[]
|
||||
{
|
||||
SCORE
|
||||
};
|
||||
opCodes[0xD0] = new OpCode[]
|
||||
{
|
||||
BYTE, STRING
|
||||
};
|
||||
opCodes[0xD1] = new OpCode[]
|
||||
{
|
||||
TEAM
|
||||
};
|
||||
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[]
|
||||
{
|
||||
BYTE
|
||||
};
|
||||
opCodes[0xFF] = new OpCode[]
|
||||
{
|
||||
STRING
|
||||
};
|
||||
/*========================== Minecraft Forge ===========================*/
|
||||
opCodes[0x01 + FORGE_PROTOCOL] = new OpCode[]
|
||||
{
|
||||
INT, STRING, BYTE, INT, BYTE, BYTE, BYTE
|
||||
};
|
||||
}
|
||||
}
|
@@ -1,19 +0,0 @@
|
||||
package net.md_5.bungee.protocol.netty;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import java.io.IOException;
|
||||
|
||||
public class Score extends Instruction
|
||||
{
|
||||
|
||||
@Override
|
||||
void read(ByteBuf in) throws IOException
|
||||
{
|
||||
STRING.read( in );
|
||||
if ( in.readByte() == 0 )
|
||||
{
|
||||
STRING.read( in );
|
||||
INT.read( in );
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,26 +0,0 @@
|
||||
package net.md_5.bungee.protocol.netty;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import java.io.IOException;
|
||||
|
||||
class Team extends Instruction
|
||||
{
|
||||
|
||||
@Override
|
||||
void read(ByteBuf in) throws IOException
|
||||
{
|
||||
STRING.read( in );
|
||||
byte mode = in.readByte();
|
||||
if ( mode == 0 || mode == 2 )
|
||||
{
|
||||
STRING.read( in );
|
||||
STRING.read( in );
|
||||
STRING.read( in );
|
||||
BYTE.read( in );
|
||||
}
|
||||
if ( mode == 0 || mode == 3 || mode == 4 )
|
||||
{
|
||||
STRING_ARRAY.read( in );
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,29 +1,8 @@
|
||||
package net.md_5.bungee.packet;
|
||||
package net.md_5.bungee.protocol.packet;
|
||||
|
||||
import net.md_5.bungee.netty.ChannelWrapper;
|
||||
|
||||
public abstract class PacketHandler
|
||||
public abstract class AbstractPacketHandler
|
||||
{
|
||||
|
||||
@Override
|
||||
public abstract String toString();
|
||||
|
||||
public void connected(ChannelWrapper channel) throws Exception
|
||||
{
|
||||
}
|
||||
|
||||
public void disconnected(ChannelWrapper channel) throws Exception
|
||||
{
|
||||
}
|
||||
|
||||
public void exception(Throwable t) throws Exception
|
||||
{
|
||||
}
|
||||
|
||||
public void handle(byte[] buf) throws Exception
|
||||
{
|
||||
}
|
||||
|
||||
public void handle(Packet0KeepAlive alive) throws Exception
|
||||
{
|
||||
}
|
||||
@@ -44,6 +23,10 @@ public abstract class PacketHandler
|
||||
{
|
||||
}
|
||||
|
||||
public void handle(Packet2CEntityProperties properties) throws Exception
|
||||
{
|
||||
}
|
||||
|
||||
public void handle(PacketC9PlayerListItem playerList) throws Exception
|
||||
{
|
||||
}
|
||||
@@ -91,4 +74,8 @@ public abstract class PacketHandler
|
||||
public void handle(PacketFFKick kick) throws Exception
|
||||
{
|
||||
}
|
||||
|
||||
public void handle(PacketCBTabComplete tabComplete) throws Exception
|
||||
{
|
||||
}
|
||||
}
|
@@ -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,49 @@
|
||||
package net.md_5.bungee.protocol.packet;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
|
||||
@Getter
|
||||
@ToString
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class Packet2CEntityProperties extends DefinedPacket
|
||||
{
|
||||
|
||||
public Packet2CEntityProperties()
|
||||
{
|
||||
super( 0x2C );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(ByteBuf buf)
|
||||
{
|
||||
buf.readInt();
|
||||
int recordCount = buf.readInt();
|
||||
for ( int i = 0; i < recordCount; i++ )
|
||||
{
|
||||
readString( buf );
|
||||
buf.readDouble();
|
||||
short size = buf.readShort();
|
||||
for ( short s = 0; s < size; s++ )
|
||||
{
|
||||
buf.skipBytes( 25 ); // long, long, double, byte
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ByteBuf buf)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@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,46 @@
|
||||
package net.md_5.bungee.protocol.packet;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@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,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 PacketCBTabComplete extends DefinedPacket
|
||||
{
|
||||
|
||||
private String cursor;
|
||||
private String[] commands;
|
||||
|
||||
private PacketCBTabComplete()
|
||||
{
|
||||
super( 0xCB );
|
||||
}
|
||||
|
||||
public PacketCBTabComplete(String[] alternatives)
|
||||
{
|
||||
this();
|
||||
commands = alternatives;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(ByteBuf buf)
|
||||
{
|
||||
cursor = readString( buf );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ByteBuf buf)
|
||||
{
|
||||
String tab = "";
|
||||
for ( String alternative : commands )
|
||||
{
|
||||
if ( tab.isEmpty() )
|
||||
{
|
||||
tab = alternative + " ";
|
||||
} else
|
||||
{
|
||||
tab += "\0" + alternative + " ";
|
||||
}
|
||||
}
|
||||
writeString( tab, 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.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,64 @@
|
||||
package net.md_5.bungee.protocol.packet;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.DataInput;
|
||||
import java.io.DataInputStream;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
import net.md_5.bungee.protocol.MinecraftInput;
|
||||
import net.md_5.bungee.protocol.MinecraftOutput;
|
||||
|
||||
@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 );
|
||||
}
|
||||
|
||||
public DataInput getStream()
|
||||
{
|
||||
return new DataInputStream( new ByteArrayInputStream( data ) );
|
||||
}
|
||||
|
||||
public MinecraftInput getMCStream()
|
||||
{
|
||||
return new MinecraftInput( Unpooled.wrappedBuffer( data ) );
|
||||
}
|
||||
}
|
@@ -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 );
|
||||
}
|
||||
}
|
@@ -1,13 +1,12 @@
|
||||
package net.md_5.bungee.protocol.netty;
|
||||
package net.md_5.bungee.protocol.skip;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import java.io.IOException;
|
||||
|
||||
public class BulkChunk extends Instruction
|
||||
{
|
||||
|
||||
@Override
|
||||
void read(ByteBuf in) throws IOException
|
||||
void read(ByteBuf in)
|
||||
{
|
||||
short count = in.readShort();
|
||||
int size = in.readInt();
|
@@ -1,7 +1,6 @@
|
||||
package net.md_5.bungee.protocol.netty;
|
||||
package net.md_5.bungee.protocol.skip;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import java.io.IOException;
|
||||
|
||||
class ByteHeader extends Instruction
|
||||
{
|
||||
@@ -14,7 +13,7 @@ class ByteHeader extends Instruction
|
||||
}
|
||||
|
||||
@Override
|
||||
void read(ByteBuf in) throws IOException
|
||||
void read(ByteBuf in)
|
||||
{
|
||||
byte size = in.readByte();
|
||||
for ( byte b = 0; b < size; b++ )
|
@@ -1,7 +1,6 @@
|
||||
package net.md_5.bungee.protocol.netty;
|
||||
package net.md_5.bungee.protocol.skip;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import java.io.IOException;
|
||||
|
||||
abstract class Instruction
|
||||
{
|
||||
@@ -19,17 +18,16 @@ abstract class Instruction
|
||||
static final Instruction LONG = new Jump( 8 );
|
||||
static final Instruction METADATA = new MetaData();
|
||||
static final Instruction OPTIONAL_MOTION = new OptionalMotion();
|
||||
static final Instruction SCORE = new Score();
|
||||
static final Instruction SHORT = new Jump( 2 );
|
||||
static final Instruction SHORT_BYTE = new ShortHeader( BYTE );
|
||||
static final Instruction SHORT_ITEM = new ShortHeader( ITEM );
|
||||
static final Instruction STRING = new ShortHeader( new Jump( 2 ) );
|
||||
static final Instruction TEAM = new Team();
|
||||
static final Instruction USHORT_BYTE = new UnsignedShortByte();
|
||||
static final Instruction OPTIONAL_WINDOW = new OptionalWindow();
|
||||
// Illegal forward references below this line
|
||||
static final Instruction BYTE_INT = new ByteHeader( INT );
|
||||
// Custom instructions
|
||||
static final Instruction STRING_ARRAY = new ShortHeader( STRING );
|
||||
|
||||
abstract void read(ByteBuf in) throws IOException;
|
||||
abstract void read(ByteBuf in);
|
||||
}
|
@@ -1,7 +1,6 @@
|
||||
package net.md_5.bungee.protocol.netty;
|
||||
package net.md_5.bungee.protocol.skip;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import java.io.IOException;
|
||||
|
||||
class IntHeader extends Instruction
|
||||
{
|
||||
@@ -14,7 +13,7 @@ class IntHeader extends Instruction
|
||||
}
|
||||
|
||||
@Override
|
||||
void read(ByteBuf in) throws IOException
|
||||
void read(ByteBuf in)
|
||||
{
|
||||
int size = in.readInt();
|
||||
for ( int i = 0; i < size; i++ )
|
@@ -1,13 +1,12 @@
|
||||
package net.md_5.bungee.protocol.netty;
|
||||
package net.md_5.bungee.protocol.skip;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import java.io.IOException;
|
||||
|
||||
class Item extends Instruction
|
||||
{
|
||||
|
||||
@Override
|
||||
void read(ByteBuf in) throws IOException
|
||||
void read(ByteBuf in)
|
||||
{
|
||||
short type = in.readShort();
|
||||
if ( type >= 0 )
|
@@ -1,7 +1,6 @@
|
||||
package net.md_5.bungee.protocol.netty;
|
||||
package net.md_5.bungee.protocol.skip;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import java.io.IOException;
|
||||
|
||||
class Jump extends Instruction
|
||||
{
|
||||
@@ -18,7 +17,7 @@ class Jump extends Instruction
|
||||
}
|
||||
|
||||
@Override
|
||||
void read(ByteBuf in) throws IOException
|
||||
void read(ByteBuf in)
|
||||
{
|
||||
in.skipBytes( len );
|
||||
}
|
@@ -1,13 +1,12 @@
|
||||
package net.md_5.bungee.protocol.netty;
|
||||
package net.md_5.bungee.protocol.skip;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import java.io.IOException;
|
||||
|
||||
class MetaData extends Instruction
|
||||
{
|
||||
|
||||
@Override
|
||||
void read(ByteBuf in) throws IOException
|
||||
void read(ByteBuf in)
|
||||
{
|
||||
int x = in.readUnsignedByte();
|
||||
while ( x != 127 )
|
@@ -1,13 +1,12 @@
|
||||
package net.md_5.bungee.protocol.netty;
|
||||
package net.md_5.bungee.protocol.skip;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import java.io.IOException;
|
||||
|
||||
class OptionalMotion extends Instruction
|
||||
{
|
||||
|
||||
@Override
|
||||
void read(ByteBuf in) throws IOException
|
||||
void read(ByteBuf in)
|
||||
{
|
||||
int data = in.readInt();
|
||||
if ( data > 0 )
|
@@ -0,0 +1,21 @@
|
||||
package net.md_5.bungee.protocol.skip;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
public class OptionalWindow extends Instruction
|
||||
{
|
||||
|
||||
@Override
|
||||
void read(ByteBuf in)
|
||||
{
|
||||
BYTE.read( in );
|
||||
byte type = in.readByte();
|
||||
STRING.read( in );
|
||||
BYTE.read( in );
|
||||
BOOLEAN.read( in );
|
||||
if ( type == 11 )
|
||||
{
|
||||
INT.read( in );
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,24 +1,24 @@
|
||||
package net.md_5.bungee.protocol.netty;
|
||||
package net.md_5.bungee.protocol.skip;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import net.md_5.bungee.protocol.PacketDefinitions;
|
||||
import net.md_5.bungee.protocol.PacketDefinitions.OpCode;
|
||||
import net.md_5.bungee.protocol.OpCode;
|
||||
import net.md_5.bungee.protocol.Protocol;
|
||||
|
||||
public class PacketReader
|
||||
{
|
||||
|
||||
private static final Instruction[][] instructions = new Instruction[ PacketDefinitions.opCodes.length ][];
|
||||
private final Instruction[][] instructions;
|
||||
|
||||
static
|
||||
public PacketReader(Protocol protocol)
|
||||
{
|
||||
instructions = new Instruction[ protocol.getOpCodes().length ][];
|
||||
for ( int i = 0; i < instructions.length; i++ )
|
||||
{
|
||||
List<Instruction> output = new ArrayList<>();
|
||||
|
||||
OpCode[] enums = PacketDefinitions.opCodes[i];
|
||||
OpCode[] enums = protocol.getOpCodes()[i];
|
||||
if ( enums != null )
|
||||
{
|
||||
for ( OpCode struct : enums )
|
||||
@@ -59,35 +59,16 @@ public class PacketReader
|
||||
}
|
||||
}
|
||||
|
||||
private static void readPacket(int packetId, ByteBuf in, int protocol) throws IOException
|
||||
public void tryRead(short packetId, ByteBuf in)
|
||||
{
|
||||
Instruction[] packetDef = null;
|
||||
if ( packetId + protocol < instructions.length )
|
||||
{
|
||||
packetDef = instructions[packetId + protocol];
|
||||
}
|
||||
Instruction[] packetDef = instructions[packetId];
|
||||
|
||||
if ( packetDef == null )
|
||||
if ( packetDef != null )
|
||||
{
|
||||
if ( protocol == PacketDefinitions.VANILLA_PROTOCOL )
|
||||
{
|
||||
throw new IOException( "Unknown packet id " + packetId );
|
||||
} else
|
||||
{
|
||||
readPacket( packetId, in, PacketDefinitions.VANILLA_PROTOCOL );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for ( Instruction instruction : packetDef )
|
||||
{
|
||||
instruction.read( in );
|
||||
}
|
||||
}
|
||||
|
||||
public static void readPacket(ByteBuf in, int protocol) throws IOException
|
||||
{
|
||||
int packetId = in.readUnsignedByte();
|
||||
readPacket( packetId, in, protocol );
|
||||
}
|
||||
}
|
@@ -1,7 +1,6 @@
|
||||
package net.md_5.bungee.protocol.netty;
|
||||
package net.md_5.bungee.protocol.skip;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import java.io.IOException;
|
||||
|
||||
class ShortHeader extends Instruction
|
||||
{
|
||||
@@ -14,7 +13,7 @@ class ShortHeader extends Instruction
|
||||
}
|
||||
|
||||
@Override
|
||||
void read(ByteBuf in) throws IOException
|
||||
void read(ByteBuf in)
|
||||
{
|
||||
short size = in.readShort();
|
||||
for ( short s = 0; s < size; s++ )
|
@@ -1,13 +1,12 @@
|
||||
package net.md_5.bungee.protocol.netty;
|
||||
package net.md_5.bungee.protocol.skip;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import java.io.IOException;
|
||||
|
||||
class UnsignedShortByte extends Instruction
|
||||
{
|
||||
|
||||
@Override
|
||||
void read(ByteBuf in) throws IOException
|
||||
void read(ByteBuf in)
|
||||
{
|
||||
int size = in.readUnsignedShort();
|
||||
in.skipBytes( 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,31 +6,41 @@
|
||||
<parent>
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-parent</artifactId>
|
||||
<version>1.5-SNAPSHOT</version>
|
||||
<version>1.6.2-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-proxy</artifactId>
|
||||
<version>1.5-SNAPSHOT</version>
|
||||
<version>1.6.2-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>BungeeCord-Proxy</name>
|
||||
<description>Proxy component of the Elastic Portal Suite</description>
|
||||
|
||||
<properties>
|
||||
<maven.build.timestamp.format>yyyyMMdd</maven.build.timestamp.format>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-codec</artifactId>
|
||||
<version>${netty.version}</version>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.2.4</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-handler</artifactId>
|
||||
<artifactId>netty-codec-http</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>
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-protocol</artifactId>
|
||||
@@ -52,13 +62,25 @@
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<version>5.1.24</version>
|
||||
<scope>compile</scope>
|
||||
<version>5.1.25</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.javassist</groupId>
|
||||
<artifactId>javassist</artifactId>
|
||||
<version>3.18.0-GA</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>BungeeCord</finalName>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<!-- Don't deploy proxy to maven repo, only APIs -->
|
||||
@@ -77,6 +99,7 @@
|
||||
<manifestEntries>
|
||||
<Main-Class>net.md_5.bungee.BungeeCord</Main-Class>
|
||||
<Implementation-Version>${describe}</Implementation-Version>
|
||||
<Specification-Version>${maven.build.timestamp}</Specification-Version>
|
||||
</manifestEntries>
|
||||
</archive>
|
||||
</configuration>
|
||||
@@ -84,7 +107,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>2.0</version>
|
||||
<version>2.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
|
@@ -1,11 +1,11 @@
|
||||
package net.md_5.bungee;
|
||||
|
||||
import com.google.common.io.ByteStreams;
|
||||
import net.md_5.bungee.log.BungeeLogger;
|
||||
import net.md_5.bungee.reconnect.YamlReconnectHandler;
|
||||
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 com.google.gson.Gson;
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelException;
|
||||
@@ -14,44 +14,55 @@ import io.netty.channel.ChannelFutureListener;
|
||||
import io.netty.channel.MultithreadEventLoopGroup;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||
import io.netty.util.ResourceLeakDetector;
|
||||
import net.md_5.bungee.config.Configuration;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
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.Logger;
|
||||
import jline.UnsupportedTerminal;
|
||||
import jline.console.ConsoleReader;
|
||||
import jline.internal.Log;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.Synchronized;
|
||||
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.ReconnectHandler;
|
||||
import net.md_5.bungee.api.TabListHandler;
|
||||
import net.md_5.bungee.api.config.ConfigurationAdapter;
|
||||
import net.md_5.bungee.api.config.ListenerInfo;
|
||||
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.plugin.Plugin;
|
||||
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.config.YamlConfig;
|
||||
import net.md_5.bungee.log.LoggingOutputStream;
|
||||
import net.md_5.bungee.netty.PipelineUtils;
|
||||
import net.md_5.bungee.packet.DefinedPacket;
|
||||
import net.md_5.bungee.packet.PacketFAPluginMessage;
|
||||
import net.md_5.bungee.scheduler.BungeeThreadPool;
|
||||
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.tab.Custom;
|
||||
import net.md_5.bungee.util.CaseInsensitiveMap;
|
||||
import org.fusesource.jansi.AnsiConsole;
|
||||
|
||||
/**
|
||||
* Main BungeeCord proxy class.
|
||||
@@ -59,14 +70,6 @@ import net.md_5.bungee.scheduler.BungeeThreadPool;
|
||||
public class BungeeCord extends ProxyServer
|
||||
{
|
||||
|
||||
/**
|
||||
* Server protocol version.
|
||||
*/
|
||||
public static final byte PROTOCOL_VERSION = 60;
|
||||
/**
|
||||
* Server game version.
|
||||
*/
|
||||
public static final String GAME_VERSION = "1.5";
|
||||
/**
|
||||
* Current operation state.
|
||||
*/
|
||||
@@ -76,14 +79,15 @@ public class BungeeCord extends ProxyServer
|
||||
*/
|
||||
public final Configuration config = new Configuration();
|
||||
/**
|
||||
* Thread pools.
|
||||
* Localization bundle.
|
||||
*/
|
||||
public final ScheduledThreadPoolExecutor executors = new BungeeThreadPool( new ThreadFactoryBuilder().setNameFormat( "Bungee Pool Thread #%1$d" ).build() );
|
||||
public final ResourceBundle bundle = ResourceBundle.getBundle( "messages_en" );
|
||||
public final MultithreadEventLoopGroup eventLoops = new NioEventLoopGroup( 0, new ThreadFactoryBuilder().setNameFormat( "Netty IO Thread #%1$d" ).build() );
|
||||
/**
|
||||
* locations.yml save thread.
|
||||
*/
|
||||
private final Timer saveThread = new Timer( "Reconnect Saver" );
|
||||
private final Timer metricsThread = new Timer( "Metrics Thread" );
|
||||
/**
|
||||
* Server socket listener.
|
||||
*/
|
||||
@@ -91,13 +95,8 @@ public class BungeeCord extends ProxyServer
|
||||
/**
|
||||
* Fully qualified connections.
|
||||
*/
|
||||
public Map<String, UserConnection> connections = new ConcurrentHashMap<>();
|
||||
/**
|
||||
* Tab list handler
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public TabListHandler tabListHandler;
|
||||
private final Map<String, UserConnection> connections = new CaseInsensitiveMap<>();
|
||||
private final ReadWriteLock connectionLock = new ReentrantReadWriteLock();
|
||||
/**
|
||||
* Plugin manager.
|
||||
*/
|
||||
@@ -113,12 +112,14 @@ public class BungeeCord extends ProxyServer
|
||||
@Getter
|
||||
private final File pluginsFolder = new File( "plugins" );
|
||||
@Getter
|
||||
private final TaskScheduler scheduler = new BungeeScheduler();
|
||||
private final BungeeScheduler 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() ) );
|
||||
private ConsoleReader consoleReader;
|
||||
@Getter
|
||||
private final Logger logger;
|
||||
public final Gson gson = new Gson();
|
||||
@Getter
|
||||
private ConnectionThrottle connectionThrottle;
|
||||
|
||||
|
||||
{
|
||||
@@ -132,6 +133,7 @@ public class BungeeCord extends ProxyServer
|
||||
getPluginManager().registerCommand( null, new CommandBungee() );
|
||||
getPluginManager().registerCommand( null, new CommandPerms() );
|
||||
getPluginManager().registerCommand( null, new CommandSend() );
|
||||
getPluginManager().registerCommand( null, new CommandFind() );
|
||||
|
||||
registerChannel( "BungeeCord" );
|
||||
}
|
||||
@@ -141,6 +143,23 @@ public class BungeeCord extends ProxyServer
|
||||
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.
|
||||
*
|
||||
@@ -148,16 +167,19 @@ public class BungeeCord extends ProxyServer
|
||||
* @throws Exception when the server cannot be started
|
||||
*/
|
||||
public static void main(String[] args) throws Exception
|
||||
{
|
||||
if ( BungeeCord.class.getPackage().getSpecificationVersion() != null )
|
||||
{
|
||||
Calendar deadline = Calendar.getInstance();
|
||||
deadline.set( 2013, 5, 26 ); // year, month, date
|
||||
if ( Calendar.getInstance().after( deadline ) )
|
||||
deadline.add( Calendar.WEEK_OF_YEAR, 2 );
|
||||
if ( Calendar.getInstance().after( new SimpleDateFormat( "yyyyMMdd" ).parse( BungeeCord.class.getPackage().getSpecificationVersion() ) ) )
|
||||
{
|
||||
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 ) );
|
||||
System.err.println( "*** Server will start in 30 seconds ***" );
|
||||
Thread.sleep( TimeUnit.SECONDS.toMillis( 30 ) );
|
||||
}
|
||||
}
|
||||
|
||||
BungeeCord bungee = new BungeeCord();
|
||||
@@ -165,16 +187,14 @@ public class BungeeCord extends ProxyServer
|
||||
bungee.getLogger().info( "Enabled BungeeCord version " + bungee.getVersion() );
|
||||
bungee.start();
|
||||
|
||||
BufferedReader br = new BufferedReader( new InputStreamReader( System.in ) );
|
||||
while ( bungee.isRunning )
|
||||
{
|
||||
String line = br.readLine();
|
||||
String line = bungee.getConsoleReader().readLine( ">" );
|
||||
if ( line != null )
|
||||
{
|
||||
boolean handled = getInstance().getPluginManager().dispatchCommand( ConsoleCommandSender.getInstance(), line );
|
||||
if ( !handled )
|
||||
if ( !bungee.getPluginManager().dispatchCommand( ConsoleCommandSender.getInstance(), line ) )
|
||||
{
|
||||
System.err.println( "Command not found" );
|
||||
bungee.getConsole().sendMessage( ChatColor.RED + "Command not found" );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -189,42 +209,45 @@ public class BungeeCord extends ProxyServer
|
||||
@Override
|
||||
public void start() throws Exception
|
||||
{
|
||||
ResourceLeakDetector.setEnabled( false ); // Eats performance
|
||||
|
||||
pluginsFolder.mkdir();
|
||||
pluginManager.loadPlugins( pluginsFolder );
|
||||
pluginManager.detectPlugins( pluginsFolder );
|
||||
config.load();
|
||||
if ( reconnectHandler == null )
|
||||
for ( ListenerInfo info : config.getListeners() )
|
||||
{
|
||||
if ( !info.isForceDefault() && reconnectHandler == null )
|
||||
{
|
||||
reconnectHandler = new YamlReconnectHandler();
|
||||
break;
|
||||
}
|
||||
}
|
||||
isRunning = true;
|
||||
|
||||
pluginManager.enablePlugins();
|
||||
pluginManager.loadAndEnablePlugins();
|
||||
|
||||
connectionThrottle = new ConnectionThrottle( config.getThrottle() );
|
||||
startListeners();
|
||||
|
||||
saveThread.scheduleAtFixedRate( new TimerTask()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
if ( getReconnectHandler() != null )
|
||||
{
|
||||
getReconnectHandler().save();
|
||||
}
|
||||
}
|
||||
}, 0, TimeUnit.MINUTES.toMillis( 5 ) );
|
||||
|
||||
new Metrics().start();
|
||||
metricsThread.scheduleAtFixedRate( new Metrics(), 0, TimeUnit.MINUTES.toMillis( Metrics.PING_INTERVAL ) );
|
||||
}
|
||||
|
||||
public void startListeners()
|
||||
{
|
||||
for ( final ListenerInfo info : config.getListeners() )
|
||||
{
|
||||
new ServerBootstrap()
|
||||
.channel( NioServerSocketChannel.class )
|
||||
.childAttr( PipelineUtils.LISTENER, info )
|
||||
.childHandler( PipelineUtils.SERVER_CHILD )
|
||||
.group( eventLoops )
|
||||
.localAddress( info.getHost() )
|
||||
.bind().addListener( new ChannelFutureListener()
|
||||
ChannelFutureListener listener = new ChannelFutureListener()
|
||||
{
|
||||
@Override
|
||||
public void operationComplete(ChannelFuture future) throws Exception
|
||||
@@ -238,7 +261,14 @@ public class BungeeCord extends ProxyServer
|
||||
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 );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -261,38 +291,68 @@ public class BungeeCord extends ProxyServer
|
||||
@Override
|
||||
public void stop()
|
||||
{
|
||||
this.isRunning = false;
|
||||
|
||||
httpClient.close();
|
||||
executors.shutdown();
|
||||
new Thread( "Shutdown Thread" )
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
BungeeCord.this.isRunning = false;
|
||||
|
||||
stopListeners();
|
||||
getLogger().info( "Closing pending connections" );
|
||||
|
||||
connectionLock.readLock().lock();
|
||||
try
|
||||
{
|
||||
getLogger().info( "Disconnecting " + connections.size() + " connections" );
|
||||
for ( UserConnection user : connections.values() )
|
||||
{
|
||||
user.disconnect( "Proxy restarting, brb." );
|
||||
user.disconnect( getTranslation( "restart" ) );
|
||||
}
|
||||
} finally
|
||||
{
|
||||
connectionLock.readLock().unlock();
|
||||
}
|
||||
|
||||
getLogger().info( "Closing IO threads" );
|
||||
eventLoops.shutdown();
|
||||
eventLoops.shutdownGracefully();
|
||||
try
|
||||
{
|
||||
eventLoops.awaitTermination( Long.MAX_VALUE, TimeUnit.NANOSECONDS );
|
||||
} catch ( InterruptedException ex )
|
||||
{
|
||||
}
|
||||
|
||||
if ( reconnectHandler != null )
|
||||
{
|
||||
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() )
|
||||
{
|
||||
try
|
||||
{
|
||||
plugin.onDisable();
|
||||
} catch ( Throwable t )
|
||||
{
|
||||
getLogger().severe( "Exception disabling plugin " + plugin.getDescription().getName() );
|
||||
t.printStackTrace();
|
||||
}
|
||||
getScheduler().cancel( plugin );
|
||||
}
|
||||
|
||||
getLogger().info( "Thank you and goodbye" );
|
||||
scheduler.shutdown();
|
||||
getLogger().info( "Thankyou and goodbye" );
|
||||
System.exit( 0 );
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcasts a packet to all clients that is connected to this instance.
|
||||
@@ -300,10 +360,17 @@ public class BungeeCord extends ProxyServer
|
||||
* @param packet the packet to send
|
||||
*/
|
||||
public void broadcast(DefinedPacket packet)
|
||||
{
|
||||
connectionLock.readLock().lock();
|
||||
try
|
||||
{
|
||||
for ( UserConnection con : connections.values() )
|
||||
{
|
||||
con.sendPacket( packet );
|
||||
con.unsafe().sendPacket( packet );
|
||||
}
|
||||
} finally
|
||||
{
|
||||
connectionLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -320,29 +387,49 @@ public class BungeeCord extends ProxyServer
|
||||
}
|
||||
|
||||
@Override
|
||||
public Logger getLogger()
|
||||
public String getTranslation(String name)
|
||||
{
|
||||
return BungeeLogger.instance;
|
||||
String translation = "<translation '" + name + "' missing>";
|
||||
try
|
||||
{
|
||||
translation = bundle.getString( name );
|
||||
} catch ( MissingResourceException ex )
|
||||
{
|
||||
}
|
||||
return translation;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked") // TODO: Abstract more
|
||||
@SuppressWarnings("unchecked")
|
||||
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
|
||||
public ProxiedPlayer getPlayer(String name)
|
||||
{
|
||||
return connections.get( name );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Server getServer(String name)
|
||||
connectionLock.readLock().lock();
|
||||
try
|
||||
{
|
||||
Collection<ProxiedPlayer> users = getServers().get( name ).getPlayers();
|
||||
return ( users != null && !users.isEmpty() ) ? users.iterator().next().getServer() : null;
|
||||
return connections.get( name );
|
||||
} finally
|
||||
{
|
||||
connectionLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -380,32 +467,25 @@ public class BungeeCord extends ProxyServer
|
||||
|
||||
public PacketFAPluginMessage registerChannels()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for ( String s : getChannels() )
|
||||
{
|
||||
sb.append( s );
|
||||
sb.append( '\00' );
|
||||
}
|
||||
byte[] payload = sb.substring( 0, sb.length() - 1 ).getBytes();
|
||||
return new PacketFAPluginMessage( "REGISTER", payload );
|
||||
return new PacketFAPluginMessage( "REGISTER", Util.format( pluginChannels, "\00" ).getBytes() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getProtocolVersion()
|
||||
{
|
||||
return PROTOCOL_VERSION;
|
||||
return Vanilla.PROTOCOL_VERSION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGameVersion()
|
||||
{
|
||||
return GAME_VERSION;
|
||||
return Vanilla.GAME_VERSION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerInfo constructServerInfo(String name, InetSocketAddress address, boolean restricted)
|
||||
public ServerInfo constructServerInfo(String name, InetSocketAddress address, String motd, boolean restricted)
|
||||
{
|
||||
return new BungeeServerInfo( name, address, restricted );
|
||||
return new BungeeServerInfo( name, address, motd, restricted );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -413,4 +493,48 @@ public class BungeeCord extends ProxyServer
|
||||
{
|
||||
return ConsoleCommandSender.getInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void broadcast(String message)
|
||||
{
|
||||
getConsole().sendMessage( message );
|
||||
// TODO: Here too
|
||||
String encoded = BungeeCord.getInstance().gson.toJson( message );
|
||||
broadcast( new Packet3Chat( "{\"text\":" + encoded + "}" ) );
|
||||
}
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
public Collection<String> getDisabledCommands()
|
||||
{
|
||||
return config.getDisabledCommands();
|
||||
}
|
||||
}
|
||||
|
@@ -1,99 +0,0 @@
|
||||
package net.md_5.bungee;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.logging.FileHandler;
|
||||
import java.util.logging.Formatter;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.LogRecord;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Logger to handle formatting and storage of the proxy's logger.
|
||||
*/
|
||||
public class BungeeLogger extends Logger
|
||||
{
|
||||
|
||||
private static final Formatter formatter = new ConsoleLogFormatter();
|
||||
static final BungeeLogger instance = new BungeeLogger();
|
||||
|
||||
public BungeeLogger()
|
||||
{
|
||||
super( "BungeeCord", null );
|
||||
try
|
||||
{
|
||||
FileHandler handler = new FileHandler( "proxy.log", 1 << 24, 8, 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 );
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,5 +1,6 @@
|
||||
package net.md_5.bungee;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import io.netty.bootstrap.Bootstrap;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelFutureListener;
|
||||
@@ -9,15 +10,14 @@ import java.net.InetSocketAddress;
|
||||
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.concurrent.ConcurrentLinkedQueue;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Synchronized;
|
||||
import net.md_5.bungee.api.Callback;
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.api.ServerPing;
|
||||
import net.md_5.bungee.api.config.ServerInfo;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
@@ -25,8 +25,8 @@ import net.md_5.bungee.api.connection.Server;
|
||||
import net.md_5.bungee.connection.PingHandler;
|
||||
import net.md_5.bungee.netty.HandlerBoss;
|
||||
import net.md_5.bungee.netty.PipelineUtils;
|
||||
import net.md_5.bungee.packet.DefinedPacket;
|
||||
import net.md_5.bungee.packet.PacketFAPluginMessage;
|
||||
import net.md_5.bungee.protocol.packet.DefinedPacket;
|
||||
import net.md_5.bungee.protocol.packet.PacketFAPluginMessage;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class BungeeServerInfo implements ServerInfo
|
||||
@@ -38,9 +38,11 @@ public class BungeeServerInfo implements ServerInfo
|
||||
private final InetSocketAddress address;
|
||||
private final Collection<ProxiedPlayer> players = new ArrayList<>();
|
||||
@Getter
|
||||
private final String motd;
|
||||
@Getter
|
||||
private final boolean restricted;
|
||||
@Getter
|
||||
private final Queue<DefinedPacket> packetQueue = new ConcurrentLinkedQueue<>();
|
||||
private final Queue<DefinedPacket> packetQueue = new LinkedList<>();
|
||||
|
||||
@Synchronized("players")
|
||||
public void addPlayer(ProxiedPlayer player)
|
||||
@@ -64,6 +66,7 @@ public class BungeeServerInfo implements ServerInfo
|
||||
@Override
|
||||
public boolean canAccess(CommandSender player)
|
||||
{
|
||||
Preconditions.checkNotNull( player, "player" );
|
||||
return !restricted || player.hasPermission( "bungeecord.server." + name );
|
||||
}
|
||||
|
||||
@@ -79,30 +82,32 @@ public class BungeeServerInfo implements ServerInfo
|
||||
return address.hashCode();
|
||||
}
|
||||
|
||||
// TODO: Don't like this method
|
||||
@Override
|
||||
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 )
|
||||
{
|
||||
server.sendData( channel, data );
|
||||
} else
|
||||
{
|
||||
synchronized ( packetQueue )
|
||||
{
|
||||
packetQueue.add( new PacketFAPluginMessage( channel, data ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ping(final Callback<ServerPing> callback)
|
||||
{
|
||||
new Bootstrap()
|
||||
.channel( NioSocketChannel.class )
|
||||
.group( BungeeCord.getInstance().eventLoops )
|
||||
.handler( PipelineUtils.BASE )
|
||||
.option( ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000 ) // TODO: Configurable
|
||||
.remoteAddress( getAddress() )
|
||||
.connect()
|
||||
.addListener( new ChannelFutureListener()
|
||||
Preconditions.checkNotNull( callback, "callback" );
|
||||
|
||||
ChannelFutureListener listener = new ChannelFutureListener()
|
||||
{
|
||||
@Override
|
||||
public void operationComplete(ChannelFuture future) throws Exception
|
||||
@@ -115,6 +120,14 @@ public class BungeeServerInfo implements ServerInfo
|
||||
callback.done( null, future.cause() );
|
||||
}
|
||||
}
|
||||
} );
|
||||
};
|
||||
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 );
|
||||
}
|
||||
}
|
||||
|
27
proxy/src/main/java/net/md_5/bungee/ConnectionThrottle.java
Normal file
27
proxy/src/main/java/net/md_5/bungee/ConnectionThrottle.java
Normal file
@@ -0,0 +1,27 @@
|
||||
package net.md_5.bungee;
|
||||
|
||||
import gnu.trove.map.hash.TObjectLongHashMap;
|
||||
import java.net.InetAddress;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class ConnectionThrottle
|
||||
{
|
||||
|
||||
private final TObjectLongHashMap<InetAddress> throttle = new TObjectLongHashMap<>();
|
||||
private final int throttleTime;
|
||||
|
||||
public void unthrottle(InetAddress address)
|
||||
{
|
||||
throttle.remove( address );
|
||||
}
|
||||
|
||||
public boolean throttle(InetAddress address)
|
||||
{
|
||||
long value = throttle.get( address );
|
||||
long currentTime = System.currentTimeMillis();
|
||||
|
||||
throttle.put( address, currentTime );
|
||||
return value != 0 && currentTime - value < throttleTime;
|
||||
}
|
||||
}
|
@@ -1,23 +1,22 @@
|
||||
package net.md_5.bungee;
|
||||
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.Key;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PublicKey;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
import java.util.Arrays;
|
||||
import java.util.Random;
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import net.md_5.bungee.packet.PacketFCEncryptionResponse;
|
||||
import net.md_5.bungee.packet.PacketFDEncryptionRequest;
|
||||
import lombok.Getter;
|
||||
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.
|
||||
@@ -27,14 +26,22 @@ public class EncryptionUtil
|
||||
|
||||
private static final Random random = new Random();
|
||||
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();
|
||||
} catch ( NoSuchAlgorithmException ex )
|
||||
{
|
||||
throw new ExceptionInInitializerError( ex );
|
||||
}
|
||||
}
|
||||
|
||||
public static PacketFDEncryptionRequest encryptRequest()
|
||||
{
|
||||
String hash = ( BungeeCord.getInstance().config.isOnlineMode() ) ? Long.toString( random.nextLong(), 16 ) : "-";
|
||||
byte[] pubKey = keys.getPublic().getEncoded();
|
||||
byte[] verify = new byte[ 4 ];
|
||||
@@ -42,22 +49,19 @@ public class EncryptionUtil
|
||||
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.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!" );
|
||||
}
|
||||
|
||||
cipher.init( Cipher.DECRYPT_MODE, keys.getPrivate() );
|
||||
byte[] shared = resp.sharedSecret;
|
||||
byte[] secret = cipher.doFinal( shared );
|
||||
|
||||
return new SecretKeySpec( secret, "AES" );
|
||||
return new SecretKeySpec( cipher.doFinal( resp.getSharedSecret() ), "AES" );
|
||||
}
|
||||
|
||||
public static Cipher getCipher(int opMode, Key shared) throws GeneralSecurityException
|
||||
@@ -66,4 +70,16 @@ public class EncryptionUtil
|
||||
cip.init( opMode, shared, new IvParameterSpec( shared.getEncoded() ) );
|
||||
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 );
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,7 @@
|
||||
package net.md_5.bungee;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
/**
|
||||
* Class to rewrite integers within packets.
|
||||
*/
|
||||
@@ -102,6 +104,10 @@ public class EntityMap
|
||||
{
|
||||
1
|
||||
};
|
||||
entityIds[0x2C] = new int[]
|
||||
{
|
||||
1
|
||||
};
|
||||
entityIds[0x37] = new int[]
|
||||
{
|
||||
1
|
||||
@@ -113,20 +119,20 @@ public class EntityMap
|
||||
};
|
||||
}
|
||||
|
||||
public static void rewrite(byte[] packet, int oldId, int newId)
|
||||
public static void rewrite(ByteBuf packet, int oldId, int newId)
|
||||
{
|
||||
int packetId = packet[0] & 0xFF;
|
||||
int packetId = packet.getUnsignedByte( 0 );
|
||||
if ( packetId == 0x1D )
|
||||
{ // bulk entity
|
||||
for ( int pos = 2; pos < packet.length; pos += 4 )
|
||||
for ( int pos = 2; pos < packet.readableBytes(); pos += 4 )
|
||||
{
|
||||
int readId = readInt( packet, pos );
|
||||
int readId = packet.getInt( pos );
|
||||
if ( readId == oldId )
|
||||
{
|
||||
setInt( packet, pos, newId );
|
||||
packet.setInt( pos, newId );
|
||||
} else if ( readId == newId )
|
||||
{
|
||||
setInt( packet, pos, oldId );
|
||||
packet.setInt( pos, oldId );
|
||||
}
|
||||
}
|
||||
} else
|
||||
@@ -136,40 +142,28 @@ public class EntityMap
|
||||
{
|
||||
for ( int pos : idArray )
|
||||
{
|
||||
int readId = readInt( packet, pos );
|
||||
int readId = packet.getInt( pos );
|
||||
if ( readId == oldId )
|
||||
{
|
||||
setInt( packet, pos, newId );
|
||||
packet.setInt( pos, newId );
|
||||
} else if ( readId == newId )
|
||||
{
|
||||
setInt( packet, pos, oldId );
|
||||
packet.setInt( pos, oldId );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( packetId == 0x17 )
|
||||
{
|
||||
int type = packet[5] & 0xFF;
|
||||
int type = packet.getUnsignedByte( 5 );
|
||||
if ( type == 60 || type == 90 )
|
||||
{
|
||||
if ( readInt( packet, 20 ) == oldId )
|
||||
int index20 = packet.getInt( 20 );
|
||||
if ( packet.readableBytes() > 24 && index20 == oldId )
|
||||
{
|
||||
setInt( packet, 20, newId );
|
||||
packet.setInt( 20, newId );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void setInt(byte[] buf, int pos, int i)
|
||||
{
|
||||
buf[pos] = (byte) ( i >> 24 );
|
||||
buf[pos + 1] = (byte) ( i >> 16 );
|
||||
buf[pos + 2] = (byte) ( i >> 8 );
|
||||
buf[pos + 3] = (byte) i;
|
||||
}
|
||||
|
||||
private static int readInt(byte[] buf, int pos)
|
||||
{
|
||||
return ( ( ( buf[pos] & 0xFF ) << 24 ) | ( ( buf[pos + 1] & 0xFF ) << 16 ) | ( ( buf[pos + 2] & 0xFF ) << 8 ) | buf[pos + 3] & 0xFF );
|
||||
}
|
||||
}
|
||||
|
@@ -8,9 +8,10 @@ import java.io.UnsupportedEncodingException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.TimerTask;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
|
||||
public class Metrics extends Thread
|
||||
public class Metrics extends TimerTask
|
||||
{
|
||||
|
||||
/**
|
||||
@@ -28,19 +29,11 @@ public class Metrics extends Thread
|
||||
/**
|
||||
* Interval of time to ping (in minutes)
|
||||
*/
|
||||
private final static int PING_INTERVAL = 10;
|
||||
|
||||
public Metrics()
|
||||
{
|
||||
super( "Metrics Gathering Thread" );
|
||||
setDaemon( true );
|
||||
}
|
||||
final static int PING_INTERVAL = 10;
|
||||
boolean firstPost = true;
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
boolean firstPost = true;
|
||||
while ( true )
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -56,14 +49,6 @@ public class Metrics extends Thread
|
||||
{
|
||||
ProxyServer.getInstance().getLogger().info( "[Metrics] " + ex.getMessage() );
|
||||
}
|
||||
try
|
||||
{
|
||||
sleep( PING_INTERVAL * 1000 * 60 );
|
||||
} catch ( InterruptedException ex )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -76,7 +61,7 @@ public class Metrics extends Thread
|
||||
data.append( encode( "guid" ) ).append( '=' ).append( encode( BungeeCord.getInstance().config.getUuid() ) );
|
||||
encodeDataPair( data, "version", ProxyServer.getInstance().getVersion() );
|
||||
encodeDataPair( data, "server", "0" );
|
||||
encodeDataPair( data, "players", Integer.toString( ProxyServer.getInstance().getPlayers().size() ) );
|
||||
encodeDataPair( data, "players", Integer.toString( ProxyServer.getInstance().getOnlineCount() ) );
|
||||
encodeDataPair( data, "revision", String.valueOf( REVISION ) );
|
||||
|
||||
// If we're pinging, append it
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user