mirror of
https://github.com/proxiodev/RedisBungee.git
synced 2026-05-03 11:40:29 +00:00
Compare commits
34 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ade1604987 | |||
| 7b2db2899e | |||
| bdda7c13c9 | |||
|
|
9696726fb5 | ||
| 86eeacbb1c | |||
| 43fe50a87f | |||
| dba8dc8ab7 | |||
| 8bfefc1ab0 | |||
| 2bc30ce5f3 | |||
| 070e416fac | |||
| 102f8591ab | |||
| 4d0222d2ae | |||
| e53f8a02ba | |||
| 08c7d89749 | |||
| d3889d8bd9 | |||
| baab263355 | |||
| df92d15743 | |||
| 3461bbcd1b | |||
| 7de457b6fa | |||
| 9f09ed21f1 | |||
| 17fdeda147 | |||
| 61dec7f03c | |||
| 165ba84791 | |||
| b683d5e226 | |||
| b27ddb6cf2 | |||
| 7c8748e262 | |||
|
|
2df0b9fc60 | ||
|
|
bd7d0f4d66 | ||
| 45b4ec65df | |||
|
|
bdd02043ea | ||
|
|
e8439950e3 | ||
|
|
fbed68e1ab | ||
|
|
a006c343a7 | ||
|
|
c9798e2371 |
37
.gitignore
vendored
37
.gitignore
vendored
@@ -1,36 +1,39 @@
|
|||||||
# Eclipse stuff
|
# Eclipse stuff
|
||||||
/.classpath
|
.classpath
|
||||||
/.project
|
.project
|
||||||
/.settings
|
.settings
|
||||||
|
|
||||||
# netbeans
|
# netbeans
|
||||||
/nbproject
|
nbproject
|
||||||
/nbactions.xml
|
nbactions.xml
|
||||||
/nb-configuration.xml
|
nb-configuration.xml
|
||||||
|
|
||||||
# we use maven!
|
# we use maven!
|
||||||
/build.xml
|
build.xml
|
||||||
|
|
||||||
# maven
|
# maven
|
||||||
/target
|
target
|
||||||
/dependency-reduced-pom.xml
|
dependency-reduced-pom.xml
|
||||||
*/target
|
|
||||||
*/dependency-reduced-pom.xml
|
|
||||||
|
|
||||||
# vim
|
# vim
|
||||||
.*.sw[a-p]
|
.*.sw[a-p]
|
||||||
|
|
||||||
# various other potential build files
|
# various other potential build files
|
||||||
/build
|
build
|
||||||
/bin
|
bin
|
||||||
/dist
|
dist
|
||||||
/manifest.mf
|
manifest.mf
|
||||||
|
|
||||||
# Mac filesystem dust
|
# Mac filesystem dust
|
||||||
/.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
# intellij
|
# intellij
|
||||||
*.iml
|
*.iml
|
||||||
*.ipr
|
*.ipr
|
||||||
*.iws
|
*.iws
|
||||||
.idea/
|
.idea/
|
||||||
|
|
||||||
|
|
||||||
|
*.versionBackup
|
||||||
|
*.versionsBackup
|
||||||
|
# java docs
|
||||||
|
javadoc
|
||||||
117
.mvn/wrapper/MavenWrapperDownloader.java
vendored
117
.mvn/wrapper/MavenWrapperDownloader.java
vendored
@@ -1,117 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2007-present the original author or 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.
|
|
||||||
*/
|
|
||||||
import java.net.*;
|
|
||||||
import java.io.*;
|
|
||||||
import java.nio.channels.*;
|
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
public class MavenWrapperDownloader {
|
|
||||||
|
|
||||||
private static final String WRAPPER_VERSION = "0.5.6";
|
|
||||||
/**
|
|
||||||
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
|
|
||||||
*/
|
|
||||||
private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
|
|
||||||
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
|
|
||||||
* use instead of the default one.
|
|
||||||
*/
|
|
||||||
private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
|
|
||||||
".mvn/wrapper/maven-wrapper.properties";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Path where the maven-wrapper.jar will be saved to.
|
|
||||||
*/
|
|
||||||
private static final String MAVEN_WRAPPER_JAR_PATH =
|
|
||||||
".mvn/wrapper/maven-wrapper.jar";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Name of the property which should be used to override the default download url for the wrapper.
|
|
||||||
*/
|
|
||||||
private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
|
|
||||||
|
|
||||||
public static void main(String args[]) {
|
|
||||||
System.out.println("- Downloader started");
|
|
||||||
File baseDirectory = new File(args[0]);
|
|
||||||
System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
|
|
||||||
|
|
||||||
// If the maven-wrapper.properties exists, read it and check if it contains a custom
|
|
||||||
// wrapperUrl parameter.
|
|
||||||
File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
|
|
||||||
String url = DEFAULT_DOWNLOAD_URL;
|
|
||||||
if(mavenWrapperPropertyFile.exists()) {
|
|
||||||
FileInputStream mavenWrapperPropertyFileInputStream = null;
|
|
||||||
try {
|
|
||||||
mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
|
|
||||||
Properties mavenWrapperProperties = new Properties();
|
|
||||||
mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
|
|
||||||
url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
|
|
||||||
} catch (IOException e) {
|
|
||||||
System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
|
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
if(mavenWrapperPropertyFileInputStream != null) {
|
|
||||||
mavenWrapperPropertyFileInputStream.close();
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
// Ignore ...
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
System.out.println("- Downloading from: " + url);
|
|
||||||
|
|
||||||
File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
|
|
||||||
if(!outputFile.getParentFile().exists()) {
|
|
||||||
if(!outputFile.getParentFile().mkdirs()) {
|
|
||||||
System.out.println(
|
|
||||||
"- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
|
|
||||||
try {
|
|
||||||
downloadFileFromURL(url, outputFile);
|
|
||||||
System.out.println("Done");
|
|
||||||
System.exit(0);
|
|
||||||
} catch (Throwable e) {
|
|
||||||
System.out.println("- Error downloading");
|
|
||||||
e.printStackTrace();
|
|
||||||
System.exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void downloadFileFromURL(String urlString, File destination) throws Exception {
|
|
||||||
if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
|
|
||||||
String username = System.getenv("MVNW_USERNAME");
|
|
||||||
char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
|
|
||||||
Authenticator.setDefault(new Authenticator() {
|
|
||||||
@Override
|
|
||||||
protected PasswordAuthentication getPasswordAuthentication() {
|
|
||||||
return new PasswordAuthentication(username, password);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
URL website = new URL(urlString);
|
|
||||||
ReadableByteChannel rbc;
|
|
||||||
rbc = Channels.newChannel(website.openStream());
|
|
||||||
FileOutputStream fos = new FileOutputStream(destination);
|
|
||||||
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
|
|
||||||
fos.close();
|
|
||||||
rbc.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
BIN
.mvn/wrapper/maven-wrapper.jar
vendored
BIN
.mvn/wrapper/maven-wrapper.jar
vendored
Binary file not shown.
2
.mvn/wrapper/maven-wrapper.properties
vendored
2
.mvn/wrapper/maven-wrapper.properties
vendored
@@ -1,2 +0,0 @@
|
|||||||
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
|
|
||||||
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
|
|
||||||
82
README.md
82
README.md
@@ -1,75 +1,63 @@
|
|||||||
# Limework fork of RedisBungee
|
# RedisBungee By Limework
|
||||||
[](https://github.com/Limework/RedisBungee/actions/workflows/maven.yml) [](https://jitpack.io/#limework/redisbungee)
|
|
||||||
|
[](https://github.com/Limework/RedisBungee/actions/workflows/maven.yml) [](https://jitpack.io/#limework/redisbungee)
|
||||||
|
|
||||||
Spigot link: [click](https://www.spigotmc.org/resources/redisbungee.87700/)
|
Spigot link: [click](https://www.spigotmc.org/resources/redisbungee.87700/)
|
||||||
|
|
||||||
The maintainer of RedisBungee has became inactive, so we have taken the development of the plugin.
|
The main project of RedisBungee is no longer maintained, so we have forked the plugin.
|
||||||
|
|
||||||
RedisBungee uses [Redis](https://redis.io) to Synchronize data between [BungeeCord](https://github.com/SpigotMC/BungeeCord) proxies
|
RedisBungee uses [Redis](https://redis.io) to Synchronize data between [BungeeCord](https://github.com/SpigotMC/BungeeCord) proxies
|
||||||
|
|
||||||
## Notice: about older versions of redis than redis 6.0
|
## Notice 1: about older versions of redis than redis 6.0
|
||||||
|
|
||||||
As of now Version 0.6.4 is only supporting redis 6.0 and above!
|
any versions of redis-bungee 0.6.4 or above only supports 6.0
|
||||||
|
Do not Open issues regarding it.
|
||||||
|
|
||||||
|
## Notice 2: users on git.limework.net
|
||||||
|
|
||||||
|
please create the issues on GitHub as its main project source.
|
||||||
|
|
||||||
## Compiling
|
## Compiling
|
||||||
|
|
||||||
Now you can use Maven without installing it using [Maven wrappe](https://github.com/takari/maven-wrapper) :)
|
|
||||||
|
|
||||||
RedisBungee is distributed as a [maven](https://maven.apache.org) project.
|
RedisBungee is distributed as a [maven](https://maven.apache.org) project.
|
||||||
|
|
||||||
To compile and installing to in your local Maven repository:
|
first, install it to your maven local repo as we don't have public maven repo.
|
||||||
|
```
|
||||||
git clone https://github.com/Limework/RedisBungee.git .
|
git clone https://github.com/ProxioDev/RedisBungee.git
|
||||||
mvnw clean install
|
cd RedisBungee
|
||||||
mvnw package
|
mvn clean install
|
||||||
|
```
|
||||||
If you have deb maven installed, you can use the `mvn` command instead.
|
then to import for bungeecord use:
|
||||||
|
```
|
||||||
And use it in your pom file.
|
<dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.imaginarycode.minecraft</groupId>
|
<groupId>com.imaginarycode.minecraft</groupId>
|
||||||
<artifactId>RedisBungee</artifactId>
|
<artifactId>RedisBungee-Bungee</artifactId>
|
||||||
<version>0.6.5-SNAPSHOT</version>
|
<version>0.7.2-SNAPSHOT</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
```
|
||||||
Or if you want to use the jitpack maven server
|
|
||||||
|
|
||||||
<repositories>
|
|
||||||
<repository>
|
|
||||||
<id>jitpack.io</id>
|
|
||||||
<url>https://jitpack.io</url>
|
|
||||||
</repository>
|
|
||||||
</repositories>
|
|
||||||
|
|
||||||
And use it in your pom file.
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.github.limework</groupId>
|
|
||||||
<artifactId>redisbungee</artifactId>
|
|
||||||
<version>0.6.4</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
|
|
||||||
## Javadocs
|
## Javadocs
|
||||||
Hosted on limework website. Version 0.6.0 ~~(note: any version 0.6.* will not have API changes.)~~
|
Check out our Java docs on github pages
|
||||||
https://limework.net/JavaDocs/RedisBungee/
|
https://proxiodev.github.io/RedisBungee-JavaDocs/0.7.2-SNAPSHOT
|
||||||
|
|
||||||
Note: we might add more api into RedisBungeeApi Class but we wont remove the old ones to
|
|
||||||
keep old plugins working....
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
**REDISBUNGEE REQUIRES A REDIS SERVER**, preferably with reasonably low latency. The default [config](https://github.com/limework/RedisBungee/blob/master/src/main/resources/example_config.yml) is saved when the plugin first starts.
|
**REDISBUNGEE REQUIRES A REDIS SERVER**, preferably with reasonably low latency. The default [config](https://github.com/proxiodev/RedisBungee/blob/master/src/main/resources/example_config.yml) is saved when the plugin first starts.
|
||||||
|
|
||||||
## License!
|
## License!
|
||||||
|
|
||||||
This project is distributed under Eclipse Public License 1.0
|
This project is distributed under Eclipse Public License 1.0
|
||||||
|
|
||||||
You can find it [here](https://github.com/Limework/RedisBungee/blob/master/LICENSE)
|
You can find it [here](https://github.com/proxiodev/RedisBungee/blob/master/LICENSE)
|
||||||
|
|
||||||
You can find the original RedisBungee by minecrafter [here](https://github.com/minecrafter/RedisBungee) or spigot page [here](https://www.spigotmc.org/resources/redisbungee.13494/)
|
You can find the original RedisBungee by minecrafter [here](https://github.com/minecrafter/RedisBungee) or spigot page [here](https://www.spigotmc.org/resources/redisbungee.13494/)
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
You can join our matrix room [here](https://matrix.to/#/!zhedzmRNSZXfuOPZUB:govindas.net?via=govindas.net&via=matrix.org)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
## YourKit
|
## YourKit
|
||||||
|
|
||||||
YourKit supports open source projects with innovative and intelligent tools for monitoring and profiling Java and .NET applications. YourKit is the creator of [YourKit Java Profiler](https://www.yourkit.com/java/profiler/), [YourKit .NET Profiler](https://www.yourkit.com/.net/profiler/) and [YourKit YouMonitor](https://www.yourkit.com/youmonitor/).
|
YourKit supports open source projects with innovative and intelligent tools for monitoring and profiling Java and .NET applications. YourKit is the creator of [YourKit Java Profiler](https://www.yourkit.com/java/profiler/), [YourKit .NET Profiler](https://www.yourkit.com/.net/profiler/) and [YourKit YouMonitor](https://www.yourkit.com/youmonitor/).
|
||||||
|
|||||||
89
RedisBungee-API/pom.xml
Normal file
89
RedisBungee-API/pom.xml
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<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">
|
||||||
|
<parent>
|
||||||
|
<artifactId>RedisBungee</artifactId>
|
||||||
|
<groupId>com.imaginarycode.minecraft</groupId>
|
||||||
|
<version>0.7.2-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>RedisBungee-API</artifactId>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
|
<version>3.3.2</version>
|
||||||
|
<configuration>
|
||||||
|
<source>8</source>
|
||||||
|
<reportOutputDirectory>../javadoc</reportOutputDirectory>
|
||||||
|
<destDir>${project.name}</destDir>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<!--
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
|
<version>3.2.4</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>package</phase>
|
||||||
|
<configuration>
|
||||||
|
<relocations>
|
||||||
|
<relocation>
|
||||||
|
<pattern>redis.clients.jedis</pattern>
|
||||||
|
<shadedPattern>com.imaginarycode.minecraft.redisbungee.internal.jedis
|
||||||
|
</shadedPattern>
|
||||||
|
</relocation>
|
||||||
|
<relocation>
|
||||||
|
<pattern>redis.clients.util</pattern>
|
||||||
|
<shadedPattern>com.imaginarycode.minecraft.redisbungee.internal.jedisutil
|
||||||
|
</shadedPattern>
|
||||||
|
</relocation>
|
||||||
|
<relocation>
|
||||||
|
<pattern>org.apache.commons.pool</pattern>
|
||||||
|
<shadedPattern>com.imaginarycode.minecraft.redisbungee.internal.commonspool
|
||||||
|
</shadedPattern>
|
||||||
|
</relocation>
|
||||||
|
<relocation>
|
||||||
|
<pattern>com.squareup.okhttp</pattern>
|
||||||
|
<shadedPattern>com.imaginarycode.minecraft.redisbungee.internal.okhttp
|
||||||
|
</shadedPattern>
|
||||||
|
</relocation>
|
||||||
|
<relocation>
|
||||||
|
<pattern>okio</pattern>
|
||||||
|
<shadedPattern>com.imaginarycode.minecraft.redisbungee.internal.okio
|
||||||
|
</shadedPattern>
|
||||||
|
</relocation>
|
||||||
|
<relocation>
|
||||||
|
<pattern>com.google</pattern>
|
||||||
|
<shadedPattern>com.imaginarycode.minecraft.redisbungee.internal.google
|
||||||
|
</shadedPattern>
|
||||||
|
</relocation>
|
||||||
|
<relocation>
|
||||||
|
<pattern>org.json</pattern>
|
||||||
|
<shadedPattern>com.imaginarycode.minecraft.redisbungee.internal.json
|
||||||
|
</shadedPattern>
|
||||||
|
</relocation>
|
||||||
|
<relocation>
|
||||||
|
<pattern>org.checkerframework</pattern>
|
||||||
|
<shadedPattern>com.imaginarycode.minecraft.redisbungee.internal.checkframework
|
||||||
|
</shadedPattern>
|
||||||
|
</relocation>
|
||||||
|
</relocations>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
-->
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>8</maven.compiler.target>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package com.imaginarycode.minecraft.redisbungee;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This used to be old plugin instance of redis-bungee, but now it's used to get the api for old plugins
|
||||||
|
*
|
||||||
|
* @deprecated its deprecated but won't be removed, so please use {@link RedisBungeeAPI#getRedisBungeeApi()}
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public class RedisBungee {
|
||||||
|
|
||||||
|
private static RedisBungeeAPI api;
|
||||||
|
|
||||||
|
public RedisBungee(RedisBungeeAPI api) {
|
||||||
|
RedisBungee.api = api;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This returns an instance of {@link RedisBungeeAPI}
|
||||||
|
*
|
||||||
|
* @deprecated Please use {@link RedisBungeeAPI#getRedisBungeeApi()} this class intended to for old plugins that no longer updated.
|
||||||
|
*
|
||||||
|
* @return the {@link RedisBungeeAPI} object instance.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public static RedisBungeeAPI getApi() {
|
||||||
|
return api;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -4,30 +4,34 @@ import com.google.common.base.Preconditions;
|
|||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
import lombok.NonNull;
|
import com.imaginarycode.minecraft.redisbungee.internal.RedisBungeePlugin;
|
||||||
import net.md_5.bungee.api.config.ServerInfo;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
import redis.clients.jedis.Jedis;
|
||||||
import redis.clients.jedis.JedisPool;
|
import redis.clients.jedis.JedisPool;
|
||||||
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class exposes some internal RedisBungee functions. You obtain an instance of this object by invoking {@link RedisBungee#getApi()}.
|
* This class exposes some internal RedisBungee functions. You obtain an instance of this object by invoking {@link RedisBungeeAPI#getRedisBungeeApi()}
|
||||||
|
* or somehow you got the Plugin instance by you can call the api using {@link RedisBungeePlugin#getApi()}.
|
||||||
*
|
*
|
||||||
* @author tuxed
|
* @author tuxed
|
||||||
* @since 0.2.3
|
* @since 0.2.3 | updated 0.7.0
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
public class RedisBungeeAPI {
|
public class RedisBungeeAPI {
|
||||||
private final RedisBungee plugin;
|
private final RedisBungeePlugin<?> plugin;
|
||||||
private final List<String> reservedChannels;
|
private final List<String> reservedChannels;
|
||||||
private static RedisBungeeAPI redisBungeeApi;
|
private static RedisBungeeAPI redisBungeeApi;
|
||||||
|
|
||||||
RedisBungeeAPI(RedisBungee plugin) {
|
RedisBungeeAPI(RedisBungeePlugin<?> plugin) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
redisBungeeApi = this;
|
redisBungeeApi = this;
|
||||||
this.reservedChannels = ImmutableList.of(
|
this.reservedChannels = ImmutableList.of(
|
||||||
"redisbungee-allservers",
|
"redisbungee-allservers",
|
||||||
"redisbungee-" + RedisBungee.getConfiguration().getServerId(),
|
"redisbungee-" + plugin.getConfiguration().getServerId(),
|
||||||
"redisbungee-data"
|
"redisbungee-data"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -57,11 +61,10 @@ public class RedisBungeeAPI {
|
|||||||
* as well, and will return local information on them.
|
* as well, and will return local information on them.
|
||||||
*
|
*
|
||||||
* @param player a player name
|
* @param player a player name
|
||||||
* @return a {@link net.md_5.bungee.api.config.ServerInfo} for the server the player is on.
|
* @return a String name for the server the player is on.
|
||||||
*/
|
*/
|
||||||
public final ServerInfo getServerFor(@NonNull UUID player) {
|
public final String getServerFor(@NonNull UUID player) {
|
||||||
String server = plugin.getDataManager().getServer(player);
|
return plugin.getDataManager().getServer(player);
|
||||||
return plugin.getProxy().getServerInfo(server);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -177,7 +180,8 @@ public class RedisBungeeAPI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a message to a PubSub channel. The channel has to be subscribed to on this, or another redisbungee instance for {@link com.imaginarycode.minecraft.redisbungee.events.PubSubMessageEvent} to fire.
|
* Sends a message to a PubSub channel. The channel has to be subscribed to on this, or another redisbungee instance for
|
||||||
|
* PubSubMessageEvent to fire.
|
||||||
*
|
*
|
||||||
* @param channel The PubSub channel
|
* @param channel The PubSub channel
|
||||||
* @param message the message body to send
|
* @param message the message body to send
|
||||||
@@ -195,7 +199,7 @@ public class RedisBungeeAPI {
|
|||||||
* @since 0.2.5
|
* @since 0.2.5
|
||||||
*/
|
*/
|
||||||
public final String getServerId() {
|
public final String getServerId() {
|
||||||
return RedisBungee.getConfiguration().getServerId();
|
return plugin.getConfiguration().getServerId();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -210,13 +214,13 @@ public class RedisBungeeAPI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register (a) PubSub channel(s), so that you may handle {@link com.imaginarycode.minecraft.redisbungee.events.PubSubMessageEvent} for it.
|
* Register (a) PubSub channel(s), so that you may handle PubSubMessageEvent for it.
|
||||||
*
|
*
|
||||||
* @param channels the channels to register
|
* @param channels the channels to register
|
||||||
* @since 0.3
|
* @since 0.3
|
||||||
*/
|
*/
|
||||||
public final void registerPubSubChannels(String... channels) {
|
public final void registerPubSubChannels(String... channels) {
|
||||||
RedisBungee.getPubSubListener().addChannel(channels);
|
plugin.getPubSubListener().addChannel(channels);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -230,7 +234,7 @@ public class RedisBungeeAPI {
|
|||||||
Preconditions.checkArgument(!reservedChannels.contains(channel), "attempting to unregister internal channel");
|
Preconditions.checkArgument(!reservedChannels.contains(channel), "attempting to unregister internal channel");
|
||||||
}
|
}
|
||||||
|
|
||||||
RedisBungee.getPubSubListener().removeChannel(channels);
|
plugin.getPubSubListener().removeChannel(channels);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -293,26 +297,37 @@ public class RedisBungeeAPI {
|
|||||||
*
|
*
|
||||||
* @param name the UUID to fetch the name for
|
* @param name the UUID to fetch the name for
|
||||||
* @param expensiveLookups whether or not to perform potentially expensive lookups
|
* @param expensiveLookups whether or not to perform potentially expensive lookups
|
||||||
* @return the UUID for the name
|
* @return the {@link UUID} for the name
|
||||||
* @since 0.3.2
|
* @since 0.3.2
|
||||||
*/
|
*/
|
||||||
public final UUID getUuidFromName(@NonNull String name, boolean expensiveLookups) {
|
public final UUID getUuidFromName(@NonNull String name, boolean expensiveLookups) {
|
||||||
return plugin.getUuidTranslator().getTranslatedUuid(name, expensiveLookups);
|
return plugin.getUuidTranslator().getTranslatedUuid(name, expensiveLookups);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This gets Redis Bungee Jedis pool
|
* This gets Redis Bungee {@link JedisPool}
|
||||||
*
|
|
||||||
* @return {@link JedisPool}
|
* @return {@link JedisPool}
|
||||||
|
* @deprecated this secluded to be removed when support for redis sentinel or redis cluster is finished, use {@link RedisBungeeAPI#requestJedis()}
|
||||||
* @since 0.6.5
|
* @since 0.6.5
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public JedisPool getJedisPool() {
|
public JedisPool getJedisPool() {
|
||||||
return this.plugin.getPool();
|
return this.plugin.getJedisPool();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This gives you instance of Jedis
|
||||||
|
* @return {@link Jedis}
|
||||||
|
* @since 0.7.0
|
||||||
|
*/
|
||||||
|
public Jedis requestJedis() {
|
||||||
|
return this.plugin.requestJedis();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This alternative to {@link RedisBungee#getApi()}
|
|
||||||
* which now deprecated. but to maintain old plugins compatibility it won't be removed.
|
|
||||||
*
|
*
|
||||||
* @return the API instance.
|
* @return the API instance.
|
||||||
* @since 0.6.5
|
* @since 0.6.5
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
package com.imaginarycode.minecraft.redisbungee.internal;
|
||||||
|
|
||||||
|
|
||||||
|
import com.google.common.collect.Multimap;
|
||||||
|
import com.google.common.collect.Multiset;
|
||||||
|
import com.google.common.io.ByteArrayDataOutput;
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public abstract class AbstractRedisBungeeListener<LE, PLE, PD, SC, PP, PM, PS> {
|
||||||
|
|
||||||
|
protected static final String ALREADY_LOGGED_IN = "§cYou are already logged on to this server. \n\nIt may help to try logging in again in a few minutes.\nIf this does not resolve your issue, please contact staff.";
|
||||||
|
|
||||||
|
protected static final String ONLINE_MODE_RECONNECT = "§cWhoops! You need to reconnect\n\nWe found someone online using your username. They were kicked and you may reconnect.\nIf this does not work, please contact staff.";
|
||||||
|
|
||||||
|
protected final RedisBungeePlugin<?> plugin;
|
||||||
|
protected final List<InetAddress> exemptAddresses;
|
||||||
|
protected final Gson gson = new Gson();
|
||||||
|
|
||||||
|
public AbstractRedisBungeeListener(RedisBungeePlugin<?> plugin, List<InetAddress> exemptAddresses) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.exemptAddresses = exemptAddresses;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void onLogin(LE event);
|
||||||
|
|
||||||
|
public abstract void onPostLogin(PLE event);
|
||||||
|
|
||||||
|
public abstract void onPlayerDisconnect(PD event);
|
||||||
|
|
||||||
|
public abstract void onServerChange(SC event);
|
||||||
|
|
||||||
|
public abstract void onPing(PP event);
|
||||||
|
|
||||||
|
public abstract void onPluginMessage(PM event);
|
||||||
|
|
||||||
|
protected void serializeMultiset(Multiset<String> collection, ByteArrayDataOutput output) {
|
||||||
|
output.writeInt(collection.elementSet().size());
|
||||||
|
for (Multiset.Entry<String> entry : collection.entrySet()) {
|
||||||
|
output.writeUTF(entry.getElement());
|
||||||
|
output.writeInt(entry.getCount());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("SameParameterValue")
|
||||||
|
protected void serializeMultimap(Multimap<String, String> collection, boolean includeNames, ByteArrayDataOutput output) {
|
||||||
|
output.writeInt(collection.keySet().size());
|
||||||
|
for (Map.Entry<String, Collection<String>> entry : collection.asMap().entrySet()) {
|
||||||
|
output.writeUTF(entry.getKey());
|
||||||
|
if (includeNames) {
|
||||||
|
serializeCollection(entry.getValue(), output);
|
||||||
|
} else {
|
||||||
|
output.writeInt(entry.getValue().size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void serializeCollection(Collection<?> collection, ByteArrayDataOutput output) {
|
||||||
|
output.writeInt(collection.size());
|
||||||
|
for (Object o : collection) {
|
||||||
|
output.writeUTF(o.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void onPubSubMessage(PS event);
|
||||||
|
}
|
||||||
@@ -1,46 +1,37 @@
|
|||||||
package com.imaginarycode.minecraft.redisbungee;
|
package com.imaginarycode.minecraft.redisbungee.internal;
|
||||||
|
|
||||||
import com.google.common.cache.Cache;
|
import com.google.common.cache.Cache;
|
||||||
import com.google.common.cache.CacheBuilder;
|
import com.google.common.cache.CacheBuilder;
|
||||||
import com.google.common.net.InetAddresses;
|
import com.google.common.net.InetAddresses;
|
||||||
|
import com.google.common.reflect.TypeToken;
|
||||||
import com.google.common.util.concurrent.UncheckedExecutionException;
|
import com.google.common.util.concurrent.UncheckedExecutionException;
|
||||||
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import com.google.gson.JsonParser;
|
import com.google.gson.JsonParser;
|
||||||
import com.google.gson.reflect.TypeToken;
|
|
||||||
import com.imaginarycode.minecraft.redisbungee.events.PlayerChangedServerNetworkEvent;
|
|
||||||
import com.imaginarycode.minecraft.redisbungee.events.PlayerJoinedNetworkEvent;
|
|
||||||
import com.imaginarycode.minecraft.redisbungee.events.PlayerLeftNetworkEvent;
|
|
||||||
import com.imaginarycode.minecraft.redisbungee.events.PubSubMessageEvent;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
|
||||||
import net.md_5.bungee.api.event.PlayerDisconnectEvent;
|
|
||||||
import net.md_5.bungee.api.event.PostLoginEvent;
|
|
||||||
import net.md_5.bungee.api.plugin.Listener;
|
|
||||||
import net.md_5.bungee.event.EventHandler;
|
|
||||||
import redis.clients.jedis.Jedis;
|
import redis.clients.jedis.Jedis;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.logging.Level;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class manages all the data that RedisBungee fetches from Redis, along with updates to that data.
|
* This class manages all the data that RedisBungee fetches from Redis, along with updates to that data.
|
||||||
*
|
*
|
||||||
* @since 0.3.3
|
* @since 0.3.3
|
||||||
*/
|
*/
|
||||||
public class DataManager implements Listener {
|
public abstract class DataManager<P, PL, PD, PS> {
|
||||||
private final RedisBungee plugin;
|
private final RedisBungeePlugin<P> plugin;
|
||||||
private final Cache<UUID, String> serverCache = createCache();
|
private final Cache<UUID, String> serverCache = createCache();
|
||||||
private final Cache<UUID, String> proxyCache = createCache();
|
private final Cache<UUID, String> proxyCache = createCache();
|
||||||
private final Cache<UUID, InetAddress> ipCache = createCache();
|
private final Cache<UUID, InetAddress> ipCache = createCache();
|
||||||
private final Cache<UUID, Long> lastOnlineCache = createCache();
|
private final Cache<UUID, Long> lastOnlineCache = createCache();
|
||||||
|
private final Gson gson = new Gson();
|
||||||
|
|
||||||
public DataManager(RedisBungee plugin) {
|
public DataManager(RedisBungeePlugin<P> plugin) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,16 +46,16 @@ public class DataManager implements Listener {
|
|||||||
private final JsonParser parser = new JsonParser();
|
private final JsonParser parser = new JsonParser();
|
||||||
|
|
||||||
public String getServer(final UUID uuid) {
|
public String getServer(final UUID uuid) {
|
||||||
ProxiedPlayer player = plugin.getProxy().getPlayer(uuid);
|
P player = plugin.getPlayer(uuid);
|
||||||
|
|
||||||
if (player != null)
|
if (player != null)
|
||||||
return player.getServer() != null ? player.getServer().getInfo().getName() : null;
|
return plugin.isPlayerOnAServer(player) ? plugin.getPlayerServerName(player) : null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return serverCache.get(uuid, new Callable<String>() {
|
return serverCache.get(uuid, new Callable<String>() {
|
||||||
@Override
|
@Override
|
||||||
public String call() throws Exception {
|
public String call() throws Exception {
|
||||||
try (Jedis tmpRsc = plugin.getPool().getResource()) {
|
try (Jedis tmpRsc = plugin.requestJedis()) {
|
||||||
return Objects.requireNonNull(tmpRsc.hget("player:" + uuid, "server"), "user not found");
|
return Objects.requireNonNull(tmpRsc.hget("player:" + uuid, "server"), "user not found");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -72,22 +63,23 @@ public class DataManager implements Listener {
|
|||||||
} catch (ExecutionException | UncheckedExecutionException e) {
|
} catch (ExecutionException | UncheckedExecutionException e) {
|
||||||
if (e.getCause() instanceof NullPointerException && e.getCause().getMessage().equals("user not found"))
|
if (e.getCause() instanceof NullPointerException && e.getCause().getMessage().equals("user not found"))
|
||||||
return null; // HACK
|
return null; // HACK
|
||||||
plugin.getLogger().log(Level.SEVERE, "Unable to get server", e);
|
plugin.logFatal("Unable to get server");
|
||||||
throw new RuntimeException("Unable to get server for " + uuid, e);
|
throw new RuntimeException("Unable to get server for " + uuid, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public String getProxy(final UUID uuid) {
|
public String getProxy(final UUID uuid) {
|
||||||
ProxiedPlayer player = plugin.getProxy().getPlayer(uuid);
|
P player = plugin.getPlayer(uuid);
|
||||||
|
|
||||||
if (player != null)
|
if (player != null)
|
||||||
return RedisBungee.getConfiguration().getServerId();
|
return plugin.getConfiguration().getServerId();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return proxyCache.get(uuid, new Callable<String>() {
|
return proxyCache.get(uuid, new Callable<String>() {
|
||||||
@Override
|
@Override
|
||||||
public String call() throws Exception {
|
public String call() throws Exception {
|
||||||
try (Jedis tmpRsc = plugin.getPool().getResource()) {
|
try (Jedis tmpRsc = plugin.requestJedis()) {
|
||||||
return Objects.requireNonNull(tmpRsc.hget("player:" + uuid, "proxy"), "user not found");
|
return Objects.requireNonNull(tmpRsc.hget("player:" + uuid, "proxy"), "user not found");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -95,22 +87,22 @@ public class DataManager implements Listener {
|
|||||||
} catch (ExecutionException | UncheckedExecutionException e) {
|
} catch (ExecutionException | UncheckedExecutionException e) {
|
||||||
if (e.getCause() instanceof NullPointerException && e.getCause().getMessage().equals("user not found"))
|
if (e.getCause() instanceof NullPointerException && e.getCause().getMessage().equals("user not found"))
|
||||||
return null; // HACK
|
return null; // HACK
|
||||||
plugin.getLogger().log(Level.SEVERE, "Unable to get proxy", e);
|
plugin.logFatal("Unable to get proxy");
|
||||||
throw new RuntimeException("Unable to get proxy for " + uuid, e);
|
throw new RuntimeException("Unable to get proxy for " + uuid, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public InetAddress getIp(final UUID uuid) {
|
public InetAddress getIp(final UUID uuid) {
|
||||||
ProxiedPlayer player = plugin.getProxy().getPlayer(uuid);
|
P player = plugin.getPlayer(uuid);
|
||||||
|
|
||||||
if (player != null)
|
if (player != null)
|
||||||
return player.getAddress().getAddress();
|
return plugin.getPlayerIp(player);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return ipCache.get(uuid, new Callable<InetAddress>() {
|
return ipCache.get(uuid, new Callable<InetAddress>() {
|
||||||
@Override
|
@Override
|
||||||
public InetAddress call() throws Exception {
|
public InetAddress call() throws Exception {
|
||||||
try (Jedis tmpRsc = plugin.getPool().getResource()) {
|
try (Jedis tmpRsc = plugin.requestJedis()) {
|
||||||
String result = tmpRsc.hget("player:" + uuid, "ip");
|
String result = tmpRsc.hget("player:" + uuid, "ip");
|
||||||
if (result == null)
|
if (result == null)
|
||||||
throw new NullPointerException("user not found");
|
throw new NullPointerException("user not found");
|
||||||
@@ -121,13 +113,13 @@ public class DataManager implements Listener {
|
|||||||
} catch (ExecutionException | UncheckedExecutionException e) {
|
} catch (ExecutionException | UncheckedExecutionException e) {
|
||||||
if (e.getCause() instanceof NullPointerException && e.getCause().getMessage().equals("user not found"))
|
if (e.getCause() instanceof NullPointerException && e.getCause().getMessage().equals("user not found"))
|
||||||
return null; // HACK
|
return null; // HACK
|
||||||
plugin.getLogger().log(Level.SEVERE, "Unable to get IP", e);
|
plugin.logFatal("Unable to get IP");
|
||||||
throw new RuntimeException("Unable to get IP for " + uuid, e);
|
throw new RuntimeException("Unable to get IP for " + uuid, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getLastOnline(final UUID uuid) {
|
public long getLastOnline(final UUID uuid) {
|
||||||
ProxiedPlayer player = plugin.getProxy().getPlayer(uuid);
|
P player = plugin.getPlayer(uuid);
|
||||||
|
|
||||||
if (player != null)
|
if (player != null)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -136,123 +128,181 @@ public class DataManager implements Listener {
|
|||||||
return lastOnlineCache.get(uuid, new Callable<Long>() {
|
return lastOnlineCache.get(uuid, new Callable<Long>() {
|
||||||
@Override
|
@Override
|
||||||
public Long call() throws Exception {
|
public Long call() throws Exception {
|
||||||
try (Jedis tmpRsc = plugin.getPool().getResource()) {
|
try (Jedis tmpRsc = plugin.requestJedis()) {
|
||||||
String result = tmpRsc.hget("player:" + uuid, "online");
|
String result = tmpRsc.hget("player:" + uuid, "online");
|
||||||
return result == null ? -1 : Long.valueOf(result);
|
return result == null ? -1 : Long.valueOf(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (ExecutionException e) {
|
} catch (ExecutionException e) {
|
||||||
plugin.getLogger().log(Level.SEVERE, "Unable to get last time online", e);
|
plugin.logFatal("Unable to get last time online");
|
||||||
throw new RuntimeException("Unable to get last time online for " + uuid, e);
|
throw new RuntimeException("Unable to get last time online for " + uuid, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void invalidate(UUID uuid) {
|
protected void invalidate(UUID uuid) {
|
||||||
ipCache.invalidate(uuid);
|
ipCache.invalidate(uuid);
|
||||||
lastOnlineCache.invalidate(uuid);
|
lastOnlineCache.invalidate(uuid);
|
||||||
serverCache.invalidate(uuid);
|
serverCache.invalidate(uuid);
|
||||||
proxyCache.invalidate(uuid);
|
proxyCache.invalidate(uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
// Invalidate all entries related to this player, since they now lie. (call invalidate(uuid))
|
||||||
public void onPostLogin(PostLoginEvent event) {
|
public abstract void onPostLogin(PL event);
|
||||||
// Invalidate all entries related to this player, since they now lie.
|
// Invalidate all entries related to this player, since they now lie. (call invalidate(uuid))
|
||||||
invalidate(event.getPlayer().getUniqueId());
|
public abstract void onPlayerDisconnect(PD event);
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
public abstract void onPubSubMessage(PS event);
|
||||||
public void onPlayerDisconnect(PlayerDisconnectEvent event) {
|
|
||||||
// Invalidate all entries related to this player, since they now lie.
|
|
||||||
invalidate(event.getPlayer().getUniqueId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
protected void handlePubSubMessage(String channel, String message) {
|
||||||
public void onPubSubMessage(PubSubMessageEvent event) {
|
if (!channel.equals("redisbungee-data"))
|
||||||
if (!event.getChannel().equals("redisbungee-data"))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Partially deserialize the message so we can look at the action
|
// Partially deserialize the message so we can look at the action
|
||||||
JsonObject jsonObject = parser.parse(event.getMessage()).getAsJsonObject();
|
JsonObject jsonObject = parser.parse(message).getAsJsonObject();
|
||||||
|
|
||||||
String source = jsonObject.get("source").getAsString();
|
String source = jsonObject.get("source").getAsString();
|
||||||
|
|
||||||
if (source.equals(RedisBungee.getConfiguration().getServerId()))
|
if (source.equals(plugin.getConfiguration().getServerId()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
DataManagerMessage.Action action = DataManagerMessage.Action.valueOf(jsonObject.get("action").getAsString());
|
DataManagerMessage.Action action = DataManagerMessage.Action.valueOf(jsonObject.get("action").getAsString());
|
||||||
|
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case JOIN:
|
case JOIN:
|
||||||
final DataManagerMessage<LoginPayload> message1 = RedisBungee.getGson().fromJson(jsonObject, new TypeToken<DataManagerMessage<LoginPayload>>() {
|
final DataManagerMessage<LoginPayload> message1 = gson.fromJson(jsonObject, new TypeToken<DataManagerMessage<LoginPayload>>() {
|
||||||
}.getType());
|
}.getType());
|
||||||
proxyCache.put(message1.getTarget(), message1.getSource());
|
proxyCache.put(message1.getTarget(), message1.getSource());
|
||||||
lastOnlineCache.put(message1.getTarget(), (long) 0);
|
lastOnlineCache.put(message1.getTarget(), (long) 0);
|
||||||
ipCache.put(message1.getTarget(), message1.getPayload().getAddress());
|
ipCache.put(message1.getTarget(), message1.getPayload().getAddress());
|
||||||
plugin.getProxy().getScheduler().runAsync(plugin, new Runnable() {
|
plugin.executeAsync(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
plugin.getProxy().getPluginManager().callEvent(new PlayerJoinedNetworkEvent(message1.getTarget()));
|
Object event;
|
||||||
|
try {
|
||||||
|
event = plugin.getNetworkJoinEventClass().getDeclaredConstructor(UUID.class).newInstance(message1.getTarget());
|
||||||
|
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
|
||||||
|
throw new RuntimeException("unable to dispatch an network join event", e);
|
||||||
|
}
|
||||||
|
plugin.callEvent(event);
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case LEAVE:
|
case LEAVE:
|
||||||
final DataManagerMessage<LogoutPayload> message2 = RedisBungee.getGson().fromJson(jsonObject, new TypeToken<DataManagerMessage<LogoutPayload>>() {
|
final DataManagerMessage<LogoutPayload> message2 = gson.fromJson(jsonObject, new TypeToken<DataManagerMessage<LogoutPayload>>() {
|
||||||
}.getType());
|
}.getType());
|
||||||
invalidate(message2.getTarget());
|
invalidate(message2.getTarget());
|
||||||
lastOnlineCache.put(message2.getTarget(), message2.getPayload().getTimestamp());
|
lastOnlineCache.put(message2.getTarget(), message2.getPayload().getTimestamp());
|
||||||
plugin.getProxy().getScheduler().runAsync(plugin, new Runnable() {
|
plugin.executeAsync(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
plugin.getProxy().getPluginManager().callEvent(new PlayerLeftNetworkEvent(message2.getTarget()));
|
Object event;
|
||||||
|
try {
|
||||||
|
event = plugin.getNetworkQuitEventClass().getDeclaredConstructor(UUID.class).newInstance(message2.getTarget());
|
||||||
|
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
|
||||||
|
throw new RuntimeException("unable to dispatch an network quit event", e);
|
||||||
|
}
|
||||||
|
plugin.callEvent(event);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case SERVER_CHANGE:
|
case SERVER_CHANGE:
|
||||||
final DataManagerMessage<ServerChangePayload> message3 = RedisBungee.getGson().fromJson(jsonObject, new TypeToken<DataManagerMessage<ServerChangePayload>>() {
|
final DataManagerMessage<ServerChangePayload> message3 = gson.fromJson(jsonObject, new TypeToken<DataManagerMessage<ServerChangePayload>>() {
|
||||||
}.getType());
|
}.getType());
|
||||||
serverCache.put(message3.getTarget(), message3.getPayload().getServer());
|
serverCache.put(message3.getTarget(), message3.getPayload().getServer());
|
||||||
plugin.getProxy().getScheduler().runAsync(plugin, new Runnable() {
|
plugin.executeAsync(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
plugin.getProxy().getPluginManager().callEvent(new PlayerChangedServerNetworkEvent(message3.getTarget(), message3.getPayload().getOldServer(), message3.getPayload().getServer()));
|
Object event;
|
||||||
|
try {
|
||||||
|
event = plugin.getServerChangeEventClass().getDeclaredConstructor(UUID.class, String.class, String.class).newInstance(message3.getTarget(), ((ServerChangePayload) message3.getPayload()).getOldServer(), ((ServerChangePayload) message3.getPayload()).getServer());
|
||||||
|
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
|
||||||
|
throw new RuntimeException("unable to dispatch an server change event", e);
|
||||||
|
}
|
||||||
|
plugin.callEvent(event);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Getter
|
public static class DataManagerMessage<T> {
|
||||||
@RequiredArgsConstructor
|
|
||||||
static class DataManagerMessage<T> {
|
|
||||||
private final UUID target;
|
private final UUID target;
|
||||||
private final String source = RedisBungee.getApi().getServerId();
|
private final String source;
|
||||||
private final Action action; // for future use!
|
private final Action action; // for future use!
|
||||||
private final T payload;
|
private final T payload;
|
||||||
|
|
||||||
enum Action {
|
public DataManagerMessage(UUID target, String source, Action action, T payload) {
|
||||||
|
this.target = target;
|
||||||
|
this.source = source;
|
||||||
|
this.action = action;
|
||||||
|
this.payload = payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID getTarget() {
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSource() {
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action getAction() {
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T getPayload() {
|
||||||
|
return payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Action {
|
||||||
JOIN,
|
JOIN,
|
||||||
LEAVE,
|
LEAVE,
|
||||||
SERVER_CHANGE
|
SERVER_CHANGE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Getter
|
public static class LoginPayload {
|
||||||
@RequiredArgsConstructor
|
|
||||||
static class LoginPayload {
|
|
||||||
private final InetAddress address;
|
private final InetAddress address;
|
||||||
|
|
||||||
|
public LoginPayload(InetAddress address) {
|
||||||
|
this.address = address;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Getter
|
public InetAddress getAddress() {
|
||||||
@RequiredArgsConstructor
|
return address;
|
||||||
static class ServerChangePayload {
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ServerChangePayload{
|
||||||
private final String server;
|
private final String server;
|
||||||
private final String oldServer;
|
private final String oldServer;
|
||||||
|
|
||||||
|
public ServerChangePayload(String server, String oldServer) {
|
||||||
|
this.server = server;
|
||||||
|
this.oldServer = oldServer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Getter
|
public String getServer() {
|
||||||
@RequiredArgsConstructor
|
return server;
|
||||||
static class LogoutPayload {
|
}
|
||||||
|
|
||||||
|
public String getOldServer() {
|
||||||
|
return oldServer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class LogoutPayload {
|
||||||
private final long timestamp;
|
private final long timestamp;
|
||||||
|
|
||||||
|
public LogoutPayload(long timestamp) {
|
||||||
|
this.timestamp = timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getTimestamp() {
|
||||||
|
return timestamp;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package com.imaginarycode.minecraft.redisbungee.internal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Since each platform have their own events' implementation for example Bungeecord events extends Event while velocity don't
|
||||||
|
*
|
||||||
|
* @author Ham1255
|
||||||
|
* @since 0.7.0
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface EventsPlatform {
|
||||||
|
|
||||||
|
Class<?> getPubSubEventClass();
|
||||||
|
|
||||||
|
Class<?> getNetworkJoinEventClass();
|
||||||
|
|
||||||
|
Class<?> getServerChangeEventClass();
|
||||||
|
|
||||||
|
Class<?> getNetworkQuitEventClass();
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package com.imaginarycode.minecraft.redisbungee.internal;
|
||||||
|
|
||||||
|
|
||||||
|
import redis.clients.jedis.JedisPubSub;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
|
||||||
|
|
||||||
|
public class JedisPubSubHandler extends JedisPubSub {
|
||||||
|
|
||||||
|
private final RedisBungeePlugin<?> plugin;
|
||||||
|
private final Class<?> eventClass;
|
||||||
|
public JedisPubSubHandler(RedisBungeePlugin<?> plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.eventClass = plugin.getPubSubEventClass();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMessage(final String s, final String s2) {
|
||||||
|
if (s2.trim().length() == 0) return;
|
||||||
|
plugin.executeAsync(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
Object event;
|
||||||
|
try {
|
||||||
|
event = eventClass.getDeclaredConstructor(String.class, String.class).newInstance(s, s2);
|
||||||
|
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
|
||||||
|
throw new RuntimeException("unable to dispatch an pubsub event", e);
|
||||||
|
}
|
||||||
|
plugin.callEvent(event);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package com.imaginarycode.minecraft.redisbungee.internal;
|
||||||
|
|
||||||
|
import redis.clients.jedis.Jedis;
|
||||||
|
import redis.clients.jedis.JedisPool;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class intended for future release to support redis sentinel or redis clusters
|
||||||
|
*
|
||||||
|
* @author Ham1255
|
||||||
|
* @since 0.7.0
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface JedisSummoner {
|
||||||
|
|
||||||
|
Jedis requestJedis();
|
||||||
|
|
||||||
|
boolean isJedisAvailable();
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
JedisPool getJedisPool();
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
package com.imaginarycode.minecraft.redisbungee.internal;
|
||||||
|
|
||||||
|
import redis.clients.jedis.Jedis;
|
||||||
|
import redis.clients.jedis.exceptions.JedisConnectionException;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
public class PubSubListener implements Runnable {
|
||||||
|
private JedisPubSubHandler jpsh;
|
||||||
|
private final Set<String> addedChannels = new HashSet<String>();
|
||||||
|
|
||||||
|
private final RedisBungeePlugin<?> plugin;
|
||||||
|
|
||||||
|
public PubSubListener(RedisBungeePlugin<?> plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
boolean broken = false;
|
||||||
|
try (Jedis rsc = plugin.requestJedis()) {
|
||||||
|
try {
|
||||||
|
|
||||||
|
jpsh = new JedisPubSubHandler(plugin);
|
||||||
|
addedChannels.add("redisbungee-" + plugin.getConfiguration().getServerId());
|
||||||
|
addedChannels.add("redisbungee-allservers");
|
||||||
|
addedChannels.add("redisbungee-data");
|
||||||
|
rsc.subscribe(jpsh, addedChannels.toArray(new String[0]));
|
||||||
|
} catch (Exception e) {
|
||||||
|
// FIXME: Extremely ugly hack
|
||||||
|
// Attempt to unsubscribe this instance and try again.
|
||||||
|
plugin.logWarn("PubSub error, attempting to recover.");
|
||||||
|
try {
|
||||||
|
jpsh.unsubscribe();
|
||||||
|
} catch (Exception e1) {
|
||||||
|
/* This may fail with
|
||||||
|
- java.net.SocketException: Broken pipe
|
||||||
|
- redis.clients.jedis.exceptions.JedisConnectionException: JedisPubSub was not subscribed to a Jedis instance
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
broken = true;
|
||||||
|
}
|
||||||
|
} catch (JedisConnectionException e) {
|
||||||
|
plugin.logWarn("PubSub error, attempting to recover in 5 secs.");
|
||||||
|
plugin.executeAsyncAfter(this, TimeUnit.SECONDS, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (broken) {
|
||||||
|
run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addChannel(String... channel) {
|
||||||
|
addedChannels.addAll(Arrays.asList(channel));
|
||||||
|
jpsh.subscribe(channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeChannel(String... channel) {
|
||||||
|
Arrays.asList(channel).forEach(addedChannels::remove);
|
||||||
|
jpsh.unsubscribe(channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void poison() {
|
||||||
|
addedChannels.clear();
|
||||||
|
jpsh.unsubscribe();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package com.imaginarycode.minecraft.redisbungee.internal;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.net.InetAddresses;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class RedisBungeeConfiguration {
|
||||||
|
private final String serverId;
|
||||||
|
private final List<InetAddress> exemptAddresses;
|
||||||
|
private static RedisBungeeConfiguration config;
|
||||||
|
|
||||||
|
public RedisBungeeConfiguration(String serverId, List<String> exemptAddresses) {
|
||||||
|
this.serverId = serverId;
|
||||||
|
|
||||||
|
ImmutableList.Builder<InetAddress> addressBuilder = ImmutableList.builder();
|
||||||
|
for (String s : exemptAddresses) {
|
||||||
|
addressBuilder.add(InetAddresses.forString(s));
|
||||||
|
}
|
||||||
|
this.exemptAddresses = addressBuilder.build();
|
||||||
|
config = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getServerId() {
|
||||||
|
return serverId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<InetAddress> getExemptAddresses() {
|
||||||
|
return exemptAddresses;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RedisBungeeConfiguration getConfig() {
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
package com.imaginarycode.minecraft.redisbungee.internal;
|
||||||
|
|
||||||
|
import com.google.common.collect.Multimap;
|
||||||
|
import com.imaginarycode.minecraft.redisbungee.RedisBungeeAPI;
|
||||||
|
import com.imaginarycode.minecraft.redisbungee.internal.util.uuid.UUIDTranslator;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This Class has all internal methods needed by every redis bungee plugin, and it can be used to implement another platforms than bungeecord
|
||||||
|
*
|
||||||
|
* @author Ham1255
|
||||||
|
* @since 0.7.0
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface RedisBungeePlugin<P> extends JedisSummoner, EventsPlatform{
|
||||||
|
|
||||||
|
default void enable() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
default void disable() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
RedisBungeeConfiguration getConfiguration();
|
||||||
|
|
||||||
|
int getCount();
|
||||||
|
|
||||||
|
int getCurrentCount();
|
||||||
|
|
||||||
|
Set<String> getLocalPlayersAsUuidStrings();
|
||||||
|
|
||||||
|
DataManager<P, ?, ?, ?> getDataManager();
|
||||||
|
|
||||||
|
Set<UUID> getPlayers();
|
||||||
|
|
||||||
|
RedisBungeeAPI getApi();
|
||||||
|
|
||||||
|
UUIDTranslator getUuidTranslator();
|
||||||
|
|
||||||
|
Multimap<String, UUID> serversToPlayers();
|
||||||
|
|
||||||
|
Set<UUID> getPlayersOnProxy(String proxyId);
|
||||||
|
|
||||||
|
void sendProxyCommand(String serverId, String command);
|
||||||
|
|
||||||
|
List<String> getServerIds();
|
||||||
|
|
||||||
|
List<String > getCurrentServerIds(boolean nag, boolean lagged);
|
||||||
|
|
||||||
|
PubSubListener getPubSubListener();
|
||||||
|
|
||||||
|
void sendChannelMessage(String channel, String message);
|
||||||
|
|
||||||
|
void executeAsync(Runnable runnable);
|
||||||
|
|
||||||
|
void executeAsyncAfter(Runnable runnable, TimeUnit timeUnit, int time);
|
||||||
|
|
||||||
|
void callEvent(Object event);
|
||||||
|
|
||||||
|
boolean isOnlineMode();
|
||||||
|
|
||||||
|
void logInfo(String msg);
|
||||||
|
|
||||||
|
void logWarn(String msg);
|
||||||
|
|
||||||
|
void logFatal(String msg);
|
||||||
|
|
||||||
|
P getPlayer(UUID uuid);
|
||||||
|
|
||||||
|
P getPlayer(String name);
|
||||||
|
|
||||||
|
UUID getPlayerUUID(String player);
|
||||||
|
|
||||||
|
String getPlayerName(UUID player);
|
||||||
|
|
||||||
|
String getPlayerServerName(P player);
|
||||||
|
|
||||||
|
boolean isPlayerOnAServer(P player);
|
||||||
|
|
||||||
|
InetAddress getPlayerIp(P player);
|
||||||
|
|
||||||
|
void sendProxyCommand(String cmd);
|
||||||
|
|
||||||
|
long getRedisTime(List<String> timeRes);
|
||||||
|
|
||||||
|
void loadConfig() throws Exception;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package com.imaginarycode.minecraft.redisbungee.internal;
|
||||||
|
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.imaginarycode.minecraft.redisbungee.RedisBungeeAPI;
|
||||||
|
import redis.clients.jedis.Jedis;
|
||||||
|
import redis.clients.jedis.Pipeline;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
public class RedisUtil {
|
||||||
|
private static final Gson gson = new Gson();
|
||||||
|
|
||||||
|
public static void cleanUpPlayer(String player, Jedis rsc) {
|
||||||
|
rsc.srem("proxy:" + RedisBungeeAPI.getRedisBungeeApi().getServerId() + ":usersOnline", player);
|
||||||
|
rsc.hdel("player:" + player, "server", "ip", "proxy");
|
||||||
|
long timestamp = System.currentTimeMillis();
|
||||||
|
rsc.hset("player:" + player, "online", String.valueOf(timestamp));
|
||||||
|
rsc.publish("redisbungee-data", gson.toJson(new DataManager.DataManagerMessage<>(
|
||||||
|
UUID.fromString(player), RedisBungeeAPI.getRedisBungeeApi().getServerId(), DataManager.DataManagerMessage.Action.LEAVE,
|
||||||
|
new DataManager.LogoutPayload(timestamp))));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void cleanUpPlayer(String player, Pipeline rsc) {
|
||||||
|
rsc.srem("proxy:" + RedisBungeeAPI.getRedisBungeeApi().getServerId() + ":usersOnline", player);
|
||||||
|
rsc.hdel("player:" + player, "server", "ip", "proxy");
|
||||||
|
long timestamp = System.currentTimeMillis();
|
||||||
|
rsc.hset("player:" + player, "online", String.valueOf(timestamp));
|
||||||
|
rsc.publish("redisbungee-data", gson.toJson(new DataManager.DataManagerMessage<>(
|
||||||
|
UUID.fromString(player), RedisBungeeAPI.getRedisBungeeApi().getServerId(), DataManager.DataManagerMessage.Action.LEAVE,
|
||||||
|
new DataManager.LogoutPayload(timestamp))));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isRedisVersionRight(String redisVersion) {
|
||||||
|
// Need to use >=6.2 to use Lua optimizations.
|
||||||
|
String[] args = redisVersion.split("\\.");
|
||||||
|
if (args.length < 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int major = Integer.parseInt(args[0]);
|
||||||
|
int minor = Integer.parseInt(args[1]);
|
||||||
|
return major >= 6 && minor >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ham1255: i am keeping this if some plugin uses this *IF*
|
||||||
|
@Deprecated
|
||||||
|
public static boolean canUseLua(String redisVersion) {
|
||||||
|
return isRedisVersionRight(redisVersion);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,14 +1,12 @@
|
|||||||
package com.imaginarycode.minecraft.redisbungee.util;
|
package com.imaginarycode.minecraft.redisbungee.internal.util;
|
||||||
|
|
||||||
import com.google.common.io.ByteStreams;
|
import com.google.common.io.ByteStreams;
|
||||||
import lombok.AccessLevel;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
|
||||||
public class IOUtil {
|
public class IOUtil {
|
||||||
public static String readInputStreamAsString(InputStream is) {
|
public static String readInputStreamAsString(InputStream is) {
|
||||||
String string;
|
String string;
|
||||||
@@ -1,32 +1,46 @@
|
|||||||
package com.imaginarycode.minecraft.redisbungee.util;
|
package com.imaginarycode.minecraft.redisbungee.internal.util;
|
||||||
|
|
||||||
import com.imaginarycode.minecraft.redisbungee.RedisBungee;
|
import com.imaginarycode.minecraft.redisbungee.internal.RedisBungeePlugin;
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import redis.clients.jedis.Jedis;
|
import redis.clients.jedis.Jedis;
|
||||||
import redis.clients.jedis.exceptions.JedisDataException;
|
import redis.clients.jedis.exceptions.JedisDataException;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class LuaManager {
|
public class LuaManager {
|
||||||
private final RedisBungee plugin;
|
private final RedisBungeePlugin<?> plugin;
|
||||||
|
|
||||||
|
public LuaManager(RedisBungeePlugin<?> plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
public Script createScript(String script) {
|
public Script createScript(String script) {
|
||||||
try (Jedis jedis = plugin.getPool().getResource()) {
|
try (Jedis jedis = plugin.requestJedis()) {
|
||||||
String hash = jedis.scriptLoad(script);
|
String hash = jedis.scriptLoad(script);
|
||||||
return new Script(script, hash);
|
return new Script(script, hash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class Script {
|
public class Script {
|
||||||
private final String script;
|
private final String script;
|
||||||
private final String hashed;
|
private final String hashed;
|
||||||
|
|
||||||
|
public Script(String script, String hashed) {
|
||||||
|
this.script = script;
|
||||||
|
this.hashed = hashed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getScript() {
|
||||||
|
return script;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHashed() {
|
||||||
|
return hashed;
|
||||||
|
}
|
||||||
|
|
||||||
public Object eval(List<String> keys, List<String> args) {
|
public Object eval(List<String> keys, List<String> args) {
|
||||||
Object data;
|
Object data;
|
||||||
|
|
||||||
try (Jedis jedis = plugin.getPool().getResource()) {
|
try (Jedis jedis = plugin.requestJedis()) {
|
||||||
try {
|
try {
|
||||||
data = jedis.evalsha(hashed, keys, args);
|
data = jedis.evalsha(hashed, keys, args);
|
||||||
} catch (JedisDataException e) {
|
} catch (JedisDataException e) {
|
||||||
@@ -1,16 +1,19 @@
|
|||||||
package com.imaginarycode.minecraft.redisbungee.util;
|
package com.imaginarycode.minecraft.redisbungee.internal.util;
|
||||||
|
|
||||||
import com.imaginarycode.minecraft.redisbungee.RedisBungee;
|
import com.imaginarycode.minecraft.redisbungee.internal.RedisBungeePlugin;
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import redis.clients.jedis.Jedis;
|
import redis.clients.jedis.Jedis;
|
||||||
import redis.clients.jedis.exceptions.JedisConnectionException;
|
import redis.clients.jedis.exceptions.JedisConnectionException;
|
||||||
|
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.logging.Level;
|
|
||||||
|
|
||||||
@AllArgsConstructor
|
|
||||||
|
|
||||||
public abstract class RedisCallable<T> implements Callable<T>, Runnable {
|
public abstract class RedisCallable<T> implements Callable<T>, Runnable {
|
||||||
private final RedisBungee plugin;
|
private final RedisBungeePlugin<?> plugin;
|
||||||
|
|
||||||
|
public RedisCallable(RedisBungeePlugin<?> plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T call() {
|
public T call() {
|
||||||
@@ -22,10 +25,10 @@ public abstract class RedisCallable<T> implements Callable<T>, Runnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private T run(boolean retry) {
|
private T run(boolean retry) {
|
||||||
try (Jedis jedis = plugin.getPool().getResource()) {
|
try (Jedis jedis = plugin.requestJedis()) {
|
||||||
return call(jedis);
|
return call(jedis);
|
||||||
} catch (JedisConnectionException e) {
|
} catch (JedisConnectionException e) {
|
||||||
plugin.getLogger().log(Level.SEVERE, "Unable to get connection", e);
|
plugin.logFatal("Unable to get connection");
|
||||||
|
|
||||||
if (!retry) {
|
if (!retry) {
|
||||||
// Wait one second before retrying the task
|
// Wait one second before retrying the task
|
||||||
@@ -1,24 +1,23 @@
|
|||||||
package com.imaginarycode.minecraft.redisbungee.util.uuid;
|
package com.imaginarycode.minecraft.redisbungee.internal.util.uuid;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.reflect.TypeToken;
|
import com.google.gson.reflect.TypeToken;
|
||||||
import com.imaginarycode.minecraft.redisbungee.RedisBungee;
|
|
||||||
import com.squareup.okhttp.OkHttpClient;
|
import com.squareup.okhttp.OkHttpClient;
|
||||||
import com.squareup.okhttp.Request;
|
import com.squareup.okhttp.Request;
|
||||||
import com.squareup.okhttp.ResponseBody;
|
import com.squareup.okhttp.ResponseBody;
|
||||||
import lombok.AccessLevel;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
|
||||||
public class NameFetcher {
|
public class NameFetcher {
|
||||||
@Setter
|
|
||||||
private static OkHttpClient httpClient;
|
private static OkHttpClient httpClient;
|
||||||
|
private static final Gson gson = new Gson();
|
||||||
|
|
||||||
|
public static void setHttpClient(OkHttpClient httpClient) {
|
||||||
|
NameFetcher.httpClient = httpClient;
|
||||||
|
}
|
||||||
|
|
||||||
public static List<String> nameHistoryFromUuid(UUID uuid) throws IOException {
|
public static List<String> nameHistoryFromUuid(UUID uuid) throws IOException {
|
||||||
String url = "https://api.mojang.com/user/profiles/" + uuid.toString().replace("-", "") + "/names";
|
String url = "https://api.mojang.com/user/profiles/" + uuid.toString().replace("-", "") + "/names";
|
||||||
@@ -29,7 +28,7 @@ public class NameFetcher {
|
|||||||
|
|
||||||
Type listType = new TypeToken<List<Name>>() {
|
Type listType = new TypeToken<List<Name>>() {
|
||||||
}.getType();
|
}.getType();
|
||||||
List<Name> names = RedisBungee.getGson().fromJson(response, listType);
|
List<Name> names = gson.fromJson(response, listType);
|
||||||
|
|
||||||
List<String> humanNames = new ArrayList<>();
|
List<String> humanNames = new ArrayList<>();
|
||||||
for (Name name : names) {
|
for (Name name : names) {
|
||||||
@@ -1,9 +1,8 @@
|
|||||||
package com.imaginarycode.minecraft.redisbungee.util.uuid;
|
package com.imaginarycode.minecraft.redisbungee.internal.util.uuid;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.imaginarycode.minecraft.redisbungee.RedisBungee;
|
import com.google.gson.Gson;
|
||||||
import com.squareup.okhttp.*;
|
import com.squareup.okhttp.*;
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -18,8 +17,13 @@ public class UUIDFetcher implements Callable<Map<String, UUID>> {
|
|||||||
private static final MediaType JSON = MediaType.parse("application/json");
|
private static final MediaType JSON = MediaType.parse("application/json");
|
||||||
private final List<String> names;
|
private final List<String> names;
|
||||||
private final boolean rateLimiting;
|
private final boolean rateLimiting;
|
||||||
|
private static final Gson gson = new Gson();
|
||||||
|
|
||||||
|
|
||||||
|
public static void setHttpClient(OkHttpClient httpClient) {
|
||||||
|
UUIDFetcher.httpClient = httpClient;
|
||||||
|
}
|
||||||
|
|
||||||
@Setter
|
|
||||||
private static OkHttpClient httpClient;
|
private static OkHttpClient httpClient;
|
||||||
|
|
||||||
private UUIDFetcher(List<String> names, boolean rateLimiting) {
|
private UUIDFetcher(List<String> names, boolean rateLimiting) {
|
||||||
@@ -39,12 +43,12 @@ public class UUIDFetcher implements Callable<Map<String, UUID>> {
|
|||||||
Map<String, UUID> uuidMap = new HashMap<>();
|
Map<String, UUID> uuidMap = new HashMap<>();
|
||||||
int requests = (int) Math.ceil(names.size() / PROFILES_PER_REQUEST);
|
int requests = (int) Math.ceil(names.size() / PROFILES_PER_REQUEST);
|
||||||
for (int i = 0; i < requests; i++) {
|
for (int i = 0; i < requests; i++) {
|
||||||
String body = RedisBungee.getGson().toJson(names.subList(i * 100, Math.min((i + 1) * 100, names.size())));
|
String body = gson.toJson(names.subList(i * 100, Math.min((i + 1) * 100, names.size())));
|
||||||
Request request = new Request.Builder().url(PROFILE_URL).post(RequestBody.create(JSON, body)).build();
|
Request request = new Request.Builder().url(PROFILE_URL).post(RequestBody.create(JSON, body)).build();
|
||||||
ResponseBody responseBody = httpClient.newCall(request).execute().body();
|
ResponseBody responseBody = httpClient.newCall(request).execute().body();
|
||||||
String response = responseBody.string();
|
String response = responseBody.string();
|
||||||
responseBody.close();
|
responseBody.close();
|
||||||
Profile[] array = RedisBungee.getGson().fromJson(response, Profile[].class);
|
Profile[] array = gson.fromJson(response, Profile[].class);
|
||||||
for (Profile profile : array) {
|
for (Profile profile : array) {
|
||||||
UUID uuid = UUIDFetcher.getUUID(profile.id);
|
UUID uuid = UUIDFetcher.getUUID(profile.id);
|
||||||
uuidMap.put(profile.name, uuid);
|
uuidMap.put(profile.name, uuid);
|
||||||
@@ -1,13 +1,12 @@
|
|||||||
package com.imaginarycode.minecraft.redisbungee.util.uuid;
|
package com.imaginarycode.minecraft.redisbungee.internal.util.uuid;
|
||||||
|
|
||||||
import com.google.common.base.Charsets;
|
import com.google.common.base.Charsets;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.imaginarycode.minecraft.redisbungee.RedisBungee;
|
import com.google.gson.Gson;
|
||||||
import lombok.Getter;
|
import com.imaginarycode.minecraft.redisbungee.internal.RedisBungeePlugin;
|
||||||
import lombok.NonNull;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
import net.md_5.bungee.api.ProxyServer;
|
|
||||||
import redis.clients.jedis.Jedis;
|
import redis.clients.jedis.Jedis;
|
||||||
import redis.clients.jedis.Pipeline;
|
import redis.clients.jedis.Pipeline;
|
||||||
import redis.clients.jedis.exceptions.JedisException;
|
import redis.clients.jedis.exceptions.JedisException;
|
||||||
@@ -17,13 +16,17 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public final class UUIDTranslator {
|
public final class UUIDTranslator {
|
||||||
private static final Pattern UUID_PATTERN = Pattern.compile("[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}");
|
private static final Pattern UUID_PATTERN = Pattern.compile("[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}");
|
||||||
private static final Pattern MOJANGIAN_UUID_PATTERN = Pattern.compile("[a-fA-F0-9]{32}");
|
private static final Pattern MOJANGIAN_UUID_PATTERN = Pattern.compile("[a-fA-F0-9]{32}");
|
||||||
private final RedisBungee plugin;
|
private final RedisBungeePlugin<?> plugin;
|
||||||
private final Map<String, CachedUUIDEntry> nameToUuidMap = new ConcurrentHashMap<>(128, 0.5f, 4);
|
private final Map<String, CachedUUIDEntry> nameToUuidMap = new ConcurrentHashMap<>(128, 0.5f, 4);
|
||||||
private final Map<UUID, CachedUUIDEntry> uuidToNameMap = new ConcurrentHashMap<>(128, 0.5f, 4);
|
private final Map<UUID, CachedUUIDEntry> uuidToNameMap = new ConcurrentHashMap<>(128, 0.5f, 4);
|
||||||
|
private static final Gson gson = new Gson();
|
||||||
|
|
||||||
|
public UUIDTranslator(RedisBungeePlugin<?> plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
private void addToMaps(String name, UUID uuid) {
|
private void addToMaps(String name, UUID uuid) {
|
||||||
// This is why I like LocalDate...
|
// This is why I like LocalDate...
|
||||||
@@ -41,8 +44,8 @@ public final class UUIDTranslator {
|
|||||||
public final UUID getTranslatedUuid(@NonNull String player, boolean expensiveLookups) {
|
public final UUID getTranslatedUuid(@NonNull String player, boolean expensiveLookups) {
|
||||||
// If the player is online, give them their UUID.
|
// If the player is online, give them their UUID.
|
||||||
// Remember, local data > remote data.
|
// Remember, local data > remote data.
|
||||||
if (ProxyServer.getInstance().getPlayer(player) != null)
|
if (plugin.getPlayer(player) != null)
|
||||||
return ProxyServer.getInstance().getPlayer(player).getUniqueId();
|
return plugin.getPlayerUUID(player);
|
||||||
|
|
||||||
// Check if it exists in the map
|
// Check if it exists in the map
|
||||||
CachedUUIDEntry cachedUUIDEntry = nameToUuidMap.get(player.toLowerCase());
|
CachedUUIDEntry cachedUUIDEntry = nameToUuidMap.get(player.toLowerCase());
|
||||||
@@ -65,16 +68,16 @@ public final class UUIDTranslator {
|
|||||||
|
|
||||||
// If we are in offline mode, UUID generation is simple.
|
// If we are in offline mode, UUID generation is simple.
|
||||||
// We don't even have to cache the UUID, since this is easy to recalculate.
|
// We don't even have to cache the UUID, since this is easy to recalculate.
|
||||||
if (!plugin.getProxy().getConfig().isOnlineMode()) {
|
if (!plugin.isOnlineMode()) {
|
||||||
return UUID.nameUUIDFromBytes(("OfflinePlayer:" + player).getBytes(Charsets.UTF_8));
|
return UUID.nameUUIDFromBytes(("OfflinePlayer:" + player).getBytes(Charsets.UTF_8));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let's try Redis.
|
// Let's try Redis.
|
||||||
try (Jedis jedis = plugin.getPool().getResource()) {
|
try (Jedis jedis = plugin.requestJedis()) {
|
||||||
String stored = jedis.hget("uuid-cache", player.toLowerCase());
|
String stored = jedis.hget("uuid-cache", player.toLowerCase());
|
||||||
if (stored != null) {
|
if (stored != null) {
|
||||||
// Found an entry value. Deserialize it.
|
// Found an entry value. Deserialize it.
|
||||||
CachedUUIDEntry entry = RedisBungee.getGson().fromJson(stored, CachedUUIDEntry.class);
|
CachedUUIDEntry entry = gson.fromJson(stored, CachedUUIDEntry.class);
|
||||||
|
|
||||||
// Check for expiry:
|
// Check for expiry:
|
||||||
if (entry.expired()) {
|
if (entry.expired()) {
|
||||||
@@ -89,14 +92,14 @@ public final class UUIDTranslator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// That didn't work. Let's ask Mojang.
|
// That didn't work. Let's ask Mojang.
|
||||||
if (!expensiveLookups || !ProxyServer.getInstance().getConfig().isOnlineMode())
|
if (!expensiveLookups || !plugin.isOnlineMode())
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
Map<String, UUID> uuidMap1;
|
Map<String, UUID> uuidMap1;
|
||||||
try {
|
try {
|
||||||
uuidMap1 = new UUIDFetcher(Collections.singletonList(player)).call();
|
uuidMap1 = new UUIDFetcher(Collections.singletonList(player)).call();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
plugin.getLogger().log(Level.SEVERE, "Unable to fetch UUID from Mojang for " + player, e);
|
plugin.logFatal("Unable to fetch UUID from Mojang for " + player);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
for (Map.Entry<String, UUID> entry : uuidMap1.entrySet()) {
|
for (Map.Entry<String, UUID> entry : uuidMap1.entrySet()) {
|
||||||
@@ -106,7 +109,7 @@ public final class UUIDTranslator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (JedisException e) {
|
} catch (JedisException e) {
|
||||||
plugin.getLogger().log(Level.SEVERE, "Unable to fetch UUID for " + player, e);
|
plugin.logFatal("Unable to fetch UUID for " + player);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null; // Nope, game over!
|
return null; // Nope, game over!
|
||||||
@@ -115,8 +118,8 @@ public final class UUIDTranslator {
|
|||||||
public final String getNameFromUuid(@NonNull UUID player, boolean expensiveLookups) {
|
public final String getNameFromUuid(@NonNull UUID player, boolean expensiveLookups) {
|
||||||
// If the player is online, give them their UUID.
|
// If the player is online, give them their UUID.
|
||||||
// Remember, local data > remote data.
|
// Remember, local data > remote data.
|
||||||
if (ProxyServer.getInstance().getPlayer(player) != null)
|
if (plugin.getPlayer(player) != null)
|
||||||
return ProxyServer.getInstance().getPlayer(player).getName();
|
return plugin.getPlayerName(player);
|
||||||
|
|
||||||
// Check if it exists in the map
|
// Check if it exists in the map
|
||||||
CachedUUIDEntry cachedUUIDEntry = uuidToNameMap.get(player);
|
CachedUUIDEntry cachedUUIDEntry = uuidToNameMap.get(player);
|
||||||
@@ -128,11 +131,11 @@ public final class UUIDTranslator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Okay, it wasn't locally cached. Let's try Redis.
|
// Okay, it wasn't locally cached. Let's try Redis.
|
||||||
try (Jedis jedis = plugin.getPool().getResource()) {
|
try (Jedis jedis = plugin.requestJedis()) {
|
||||||
String stored = jedis.hget("uuid-cache", player.toString());
|
String stored = jedis.hget("uuid-cache", player.toString());
|
||||||
if (stored != null) {
|
if (stored != null) {
|
||||||
// Found an entry value. Deserialize it.
|
// Found an entry value. Deserialize it.
|
||||||
CachedUUIDEntry entry = RedisBungee.getGson().fromJson(stored, CachedUUIDEntry.class);
|
CachedUUIDEntry entry = gson.fromJson(stored, CachedUUIDEntry.class);
|
||||||
|
|
||||||
// Check for expiry:
|
// Check for expiry:
|
||||||
if (entry.expired()) {
|
if (entry.expired()) {
|
||||||
@@ -147,7 +150,7 @@ public final class UUIDTranslator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!expensiveLookups || !ProxyServer.getInstance().getConfig().isOnlineMode())
|
if (!expensiveLookups || !plugin.isOnlineMode())
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
// That didn't work. Let's ask Mojang. This call may fail, because Mojang is insane.
|
// That didn't work. Let's ask Mojang. This call may fail, because Mojang is insane.
|
||||||
@@ -156,7 +159,7 @@ public final class UUIDTranslator {
|
|||||||
List<String> nameHist = NameFetcher.nameHistoryFromUuid(player);
|
List<String> nameHist = NameFetcher.nameHistoryFromUuid(player);
|
||||||
name = Iterables.getLast(nameHist, null);
|
name = Iterables.getLast(nameHist, null);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
plugin.getLogger().log(Level.SEVERE, "Unable to fetch name from Mojang for " + player, e);
|
plugin.logFatal("Unable to fetch name from Mojang for " + player);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,30 +170,46 @@ public final class UUIDTranslator {
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
} catch (JedisException e) {
|
} catch (JedisException e) {
|
||||||
plugin.getLogger().log(Level.SEVERE, "Unable to fetch name for " + player, e);
|
plugin.logFatal("Unable to fetch name for " + player);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void persistInfo(String name, UUID uuid, Jedis jedis) {
|
public final void persistInfo(String name, UUID uuid, Jedis jedis) {
|
||||||
addToMaps(name, uuid);
|
addToMaps(name, uuid);
|
||||||
String json = RedisBungee.getGson().toJson(uuidToNameMap.get(uuid));
|
String json = gson.toJson(uuidToNameMap.get(uuid));
|
||||||
jedis.hmset("uuid-cache", ImmutableMap.of(name.toLowerCase(), json, uuid.toString(), json));
|
jedis.hmset("uuid-cache", ImmutableMap.of(name.toLowerCase(), json, uuid.toString(), json));
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void persistInfo(String name, UUID uuid, Pipeline jedis) {
|
public final void persistInfo(String name, UUID uuid, Pipeline jedis) {
|
||||||
addToMaps(name, uuid);
|
addToMaps(name, uuid);
|
||||||
String json = RedisBungee.getGson().toJson(uuidToNameMap.get(uuid));
|
String json = gson.toJson(uuidToNameMap.get(uuid));
|
||||||
jedis.hmset("uuid-cache", ImmutableMap.of(name.toLowerCase(), json, uuid.toString(), json));
|
jedis.hmset("uuid-cache", ImmutableMap.of(name.toLowerCase(), json, uuid.toString(), json));
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
private static class CachedUUIDEntry {
|
||||||
@Getter
|
|
||||||
private class CachedUUIDEntry {
|
|
||||||
private final String name;
|
private final String name;
|
||||||
private final UUID uuid;
|
private final UUID uuid;
|
||||||
private final Calendar expiry;
|
private final Calendar expiry;
|
||||||
|
|
||||||
|
public CachedUUIDEntry(String name, UUID uuid, Calendar expiry) {
|
||||||
|
this.name = name;
|
||||||
|
this.uuid = uuid;
|
||||||
|
this.expiry = expiry;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID getUuid() {
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Calendar getExpiry() {
|
||||||
|
return expiry;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean expired() {
|
public boolean expired() {
|
||||||
return Calendar.getInstance().after(expiry);
|
return Calendar.getInstance().after(expiry);
|
||||||
}
|
}
|
||||||
@@ -8,21 +8,16 @@ redis-port: 6379
|
|||||||
# OPTIONAL: If your Redis server uses AUTH, set the password required.
|
# OPTIONAL: If your Redis server uses AUTH, set the password required.
|
||||||
redis-password: ""
|
redis-password: ""
|
||||||
# Maximum connections that will be maintained to the Redis server.
|
# Maximum connections that will be maintained to the Redis server.
|
||||||
# The default is 8. This setting should be left as-is unless you have some wildly
|
# The default is 10. This setting should be left as-is unless you have some wildly
|
||||||
# inefficient plugins or a lot of players.
|
# inefficient plugins or a lot of players.
|
||||||
max-redis-connections: 8
|
max-redis-connections: 10
|
||||||
|
|
||||||
# since redis can support ssl by version 6 you can use ssl in redis bungee too!
|
# since redis can support ssl by version 6 you can use ssl in redis bungee too!
|
||||||
# you must disable this if redis version is under 6 you must disable this or connection wont work!!!
|
# but there is more configuration needed to work see https://github.com/ProxioDev/RedisBungee/issues/18
|
||||||
useSSL: false
|
useSSL: false
|
||||||
|
|
||||||
# An identifier for this BungeeCord instance. Will randomly generate if leaving it blank.
|
# An identifier for this BungeeCord instance. Will randomly generate if leaving it blank.
|
||||||
server-id: "test1"
|
server-id: "test1"
|
||||||
# Should use random string? if this is enabled the proxy id will be like this if server-id is test1: "test1-66cd2aeb-91f3-43a7-a106-e0307b098652"
|
|
||||||
# or if id is limework-bungee it will be "limework-bungee-66cd2aeb-91f3-43a7-a106-e0307b098652"
|
|
||||||
# this great for servers who run replicas in Kubernetes or any auto deploying replica service
|
|
||||||
# and used for if proxy died in a kubernetes network and deleted then new proxy setup itself.
|
|
||||||
use-random-id-string: false
|
|
||||||
|
|
||||||
# Whether or not RedisBungee should install its version of regular BungeeCord commands.
|
# Whether or not RedisBungee should install its version of regular BungeeCord commands.
|
||||||
# Often, the RedisBungee commands are desired, but in some cases someone may wish to
|
# Often, the RedisBungee commands are desired, but in some cases someone may wish to
|
||||||
130
RedisBungee-Bungee/pom.xml
Normal file
130
RedisBungee-Bungee/pom.xml
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<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">
|
||||||
|
<parent>
|
||||||
|
<artifactId>RedisBungee</artifactId>
|
||||||
|
<groupId>com.imaginarycode.minecraft</groupId>
|
||||||
|
<version>0.7.2-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>RedisBungee-Bungee</artifactId>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>8</maven.compiler.target>
|
||||||
|
</properties>
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>bungeecord-repo</id>
|
||||||
|
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<resources>
|
||||||
|
<resource>
|
||||||
|
<directory>src/main/resources</directory>
|
||||||
|
<filtering>true</filtering>
|
||||||
|
</resource>
|
||||||
|
</resources>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.8.1</version>
|
||||||
|
<configuration>
|
||||||
|
<source>1.8</source>
|
||||||
|
<target>1.8</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
|
<version>3.3.2</version>
|
||||||
|
<configuration>
|
||||||
|
<source>8</source>
|
||||||
|
<reportOutputDirectory>../javadoc</reportOutputDirectory>
|
||||||
|
<destDir>${project.name}</destDir>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
|
<version>3.2.4</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals><goal>shade</goal></goals>
|
||||||
|
<configuration>
|
||||||
|
<relocations>
|
||||||
|
<relocation>
|
||||||
|
<pattern>redis.clients.jedis</pattern>
|
||||||
|
<shadedPattern>com.imaginarycode.minecraft.redisbungee.internal.jedis
|
||||||
|
</shadedPattern>
|
||||||
|
</relocation>
|
||||||
|
<relocation>
|
||||||
|
<pattern>redis.clients.util</pattern>
|
||||||
|
<shadedPattern>com.imaginarycode.minecraft.redisbungee.internal.jedisutil
|
||||||
|
</shadedPattern>
|
||||||
|
</relocation>
|
||||||
|
<relocation>
|
||||||
|
<pattern>org.apache.commons.pool</pattern>
|
||||||
|
<shadedPattern>com.imaginarycode.minecraft.redisbungee.internal.commonspool
|
||||||
|
</shadedPattern>
|
||||||
|
</relocation>
|
||||||
|
<relocation>
|
||||||
|
<pattern>com.squareup.okhttp</pattern>
|
||||||
|
<shadedPattern>com.imaginarycode.minecraft.redisbungee.internal.okhttp
|
||||||
|
</shadedPattern>
|
||||||
|
</relocation>
|
||||||
|
<relocation>
|
||||||
|
<pattern>okio</pattern>
|
||||||
|
<shadedPattern>com.imaginarycode.minecraft.redisbungee.internal.okio
|
||||||
|
</shadedPattern>
|
||||||
|
</relocation>
|
||||||
|
<relocation>
|
||||||
|
<pattern>com.google</pattern>
|
||||||
|
<shadedPattern>com.imaginarycode.minecraft.redisbungee.internal.google
|
||||||
|
</shadedPattern>
|
||||||
|
</relocation>
|
||||||
|
<relocation>
|
||||||
|
<pattern>org.json</pattern>
|
||||||
|
<shadedPattern>com.imaginarycode.minecraft.redisbungee.internal.json
|
||||||
|
</shadedPattern>
|
||||||
|
</relocation>
|
||||||
|
<relocation>
|
||||||
|
<pattern>org.checkerframework</pattern>
|
||||||
|
<shadedPattern>com.imaginarycode.minecraft.redisbungee.internal.checkframework
|
||||||
|
</shadedPattern>
|
||||||
|
</relocation>
|
||||||
|
</relocations>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.imaginarycode.minecraft</groupId>
|
||||||
|
<artifactId>RedisBungee-API</artifactId>
|
||||||
|
<version>${parent.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.imaginarycode.minecraft</groupId>
|
||||||
|
<artifactId>RedisBungee-BungeeEvents</artifactId>
|
||||||
|
<version>${parent.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.md-5</groupId>
|
||||||
|
<artifactId>bungeecord-api</artifactId>
|
||||||
|
<version>1.17-R0.1-SNAPSHOT</version>
|
||||||
|
<type>jar</type>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package com.imaginarycode.minecraft.redisbungee;
|
||||||
|
|
||||||
|
import com.imaginarycode.minecraft.redisbungee.events.PubSubMessageEvent;
|
||||||
|
import com.imaginarycode.minecraft.redisbungee.internal.DataManager;
|
||||||
|
import com.imaginarycode.minecraft.redisbungee.internal.RedisBungeePlugin;
|
||||||
|
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||||
|
import net.md_5.bungee.api.event.PlayerDisconnectEvent;
|
||||||
|
import net.md_5.bungee.api.event.PostLoginEvent;
|
||||||
|
import net.md_5.bungee.api.plugin.Listener;
|
||||||
|
import net.md_5.bungee.event.EventHandler;
|
||||||
|
|
||||||
|
public class BungeeDataManager extends DataManager<ProxiedPlayer, PostLoginEvent, PlayerDisconnectEvent, PubSubMessageEvent> implements Listener {
|
||||||
|
|
||||||
|
public BungeeDataManager(RedisBungeePlugin<ProxiedPlayer> plugin) {
|
||||||
|
super(plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@EventHandler
|
||||||
|
public void onPostLogin(PostLoginEvent event) {
|
||||||
|
invalidate(event.getPlayer().getUniqueId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@EventHandler
|
||||||
|
public void onPlayerDisconnect(PlayerDisconnectEvent event) {
|
||||||
|
invalidate(event.getPlayer().getUniqueId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@EventHandler
|
||||||
|
public void onPubSubMessage(PubSubMessageEvent event) {
|
||||||
|
handlePubSubMessage(event.getChannel(), event.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package com.imaginarycode.minecraft.redisbungee;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.imaginarycode.minecraft.redisbungee.internal.DataManager;
|
||||||
|
import net.md_5.bungee.api.connection.PendingConnection;
|
||||||
|
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||||
|
import redis.clients.jedis.Pipeline;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class RBUtils {
|
||||||
|
|
||||||
|
private static final Gson gson = new Gson();
|
||||||
|
|
||||||
|
protected static void createPlayer(ProxiedPlayer player, Pipeline pipeline, boolean fireEvent) {
|
||||||
|
createPlayer(player.getPendingConnection(), pipeline, fireEvent);
|
||||||
|
if (player.getServer() != null)
|
||||||
|
pipeline.hset("player:" + player.getUniqueId().toString(), "server", player.getServer().getInfo().getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static void createPlayer(PendingConnection connection, Pipeline pipeline, boolean fireEvent) {
|
||||||
|
Map<String, String> playerData = new HashMap<>(4);
|
||||||
|
playerData.put("online", "0");
|
||||||
|
playerData.put("ip", connection.getAddress().getAddress().getHostAddress());
|
||||||
|
playerData.put("proxy", RedisBungeeAPI.getRedisBungeeApi().getServerId());
|
||||||
|
|
||||||
|
pipeline.sadd("proxy:" + RedisBungeeAPI.getRedisBungeeApi().getServerId() + ":usersOnline", connection.getUniqueId().toString());
|
||||||
|
pipeline.hmset("player:" + connection.getUniqueId().toString(), playerData);
|
||||||
|
|
||||||
|
if (fireEvent) {
|
||||||
|
pipeline.publish("redisbungee-data", gson.toJson(new DataManager.DataManagerMessage<>(
|
||||||
|
connection.getUniqueId(), RedisBungeeAPI.getRedisBungeeApi().getServerId(), DataManager.DataManagerMessage.Action.JOIN,
|
||||||
|
new DataManager.LoginPayload(connection.getAddress().getAddress()))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -2,31 +2,40 @@ package com.imaginarycode.minecraft.redisbungee;
|
|||||||
|
|
||||||
import com.google.common.cache.Cache;
|
import com.google.common.cache.Cache;
|
||||||
import com.google.common.cache.CacheBuilder;
|
import com.google.common.cache.CacheBuilder;
|
||||||
import com.google.common.collect.*;
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.ImmutableMultimap;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.common.collect.Multimap;
|
||||||
import com.google.common.io.ByteStreams;
|
import com.google.common.io.ByteStreams;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
|
import com.imaginarycode.minecraft.redisbungee.commands.RedisBungeeCommands;
|
||||||
|
import com.imaginarycode.minecraft.redisbungee.events.PlayerChangedServerNetworkEvent;
|
||||||
|
import com.imaginarycode.minecraft.redisbungee.events.PlayerJoinedNetworkEvent;
|
||||||
import com.imaginarycode.minecraft.redisbungee.events.PubSubMessageEvent;
|
import com.imaginarycode.minecraft.redisbungee.events.PubSubMessageEvent;
|
||||||
import com.imaginarycode.minecraft.redisbungee.util.*;
|
import com.imaginarycode.minecraft.redisbungee.internal.*;
|
||||||
import com.imaginarycode.minecraft.redisbungee.util.uuid.NameFetcher;
|
import com.imaginarycode.minecraft.redisbungee.internal.util.IOUtil;
|
||||||
import com.imaginarycode.minecraft.redisbungee.util.uuid.UUIDFetcher;
|
import com.imaginarycode.minecraft.redisbungee.internal.util.LuaManager;
|
||||||
import com.imaginarycode.minecraft.redisbungee.util.uuid.UUIDTranslator;
|
import com.imaginarycode.minecraft.redisbungee.internal.util.uuid.NameFetcher;
|
||||||
|
import com.imaginarycode.minecraft.redisbungee.internal.util.uuid.UUIDFetcher;
|
||||||
|
import com.imaginarycode.minecraft.redisbungee.internal.util.uuid.UUIDTranslator;
|
||||||
import com.squareup.okhttp.Dispatcher;
|
import com.squareup.okhttp.Dispatcher;
|
||||||
import com.squareup.okhttp.OkHttpClient;
|
import com.squareup.okhttp.OkHttpClient;
|
||||||
import lombok.AccessLevel;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
import lombok.NonNull;
|
|
||||||
import net.md_5.bungee.api.ProxyServer;
|
import net.md_5.bungee.api.ProxyServer;
|
||||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||||
|
import net.md_5.bungee.api.plugin.Event;
|
||||||
import net.md_5.bungee.api.plugin.Plugin;
|
import net.md_5.bungee.api.plugin.Plugin;
|
||||||
import net.md_5.bungee.config.Configuration;
|
import net.md_5.bungee.config.Configuration;
|
||||||
import net.md_5.bungee.config.ConfigurationProvider;
|
import net.md_5.bungee.config.ConfigurationProvider;
|
||||||
import net.md_5.bungee.config.YamlConfiguration;
|
import net.md_5.bungee.config.YamlConfiguration;
|
||||||
import redis.clients.jedis.*;
|
import redis.clients.jedis.Jedis;
|
||||||
|
import redis.clients.jedis.JedisPool;
|
||||||
|
import redis.clients.jedis.JedisPoolConfig;
|
||||||
|
import redis.clients.jedis.Pipeline;
|
||||||
import redis.clients.jedis.exceptions.JedisConnectionException;
|
import redis.clients.jedis.exceptions.JedisConnectionException;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
import java.net.InetAddress;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
@@ -34,39 +43,21 @@ import java.util.logging.Level;
|
|||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
|
|
||||||
/**
|
public class RedisBungeeBungeePlugin extends Plugin implements RedisBungeePlugin<ProxiedPlayer> {
|
||||||
* The RedisBungee plugin.
|
|
||||||
* <p>
|
private static final Gson gson = new Gson();
|
||||||
* The only function of interest is {@link #getApi()}, which deprecated now,
|
private RedisBungeeAPI api;
|
||||||
* Please check {@link RedisBungeeAPI#getRedisBungeeApi()},
|
private PubSubListener psl = null;
|
||||||
*
|
private JedisPool jedisPool;
|
||||||
* which exposes some functions in this class.
|
|
||||||
* but if you want old version support,
|
|
||||||
* then you can use old method {@link #getApi()}
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public final class RedisBungee extends Plugin {
|
|
||||||
@Getter
|
|
||||||
private static Gson gson = new Gson();
|
|
||||||
private static RedisBungeeAPI api;
|
|
||||||
@Getter(AccessLevel.PACKAGE)
|
|
||||||
private static PubSubListener psl = null;
|
|
||||||
@Getter
|
|
||||||
private JedisPool pool;
|
|
||||||
@Getter
|
|
||||||
private UUIDTranslator uuidTranslator;
|
private UUIDTranslator uuidTranslator;
|
||||||
@Getter(AccessLevel.PACKAGE)
|
private RedisBungeeConfiguration configuration;
|
||||||
private static RedisBungeeConfiguration configuration;
|
private BungeeDataManager dataManager;
|
||||||
@Getter
|
private OkHttpClient httpClient;
|
||||||
private DataManager dataManager;
|
|
||||||
@Getter
|
|
||||||
private static OkHttpClient httpClient;
|
|
||||||
private volatile List<String> serverIds;
|
private volatile List<String> serverIds;
|
||||||
private final AtomicInteger nagAboutServers = new AtomicInteger();
|
private final AtomicInteger nagAboutServers = new AtomicInteger();
|
||||||
private final AtomicInteger globalPlayerCount = new AtomicInteger();
|
private final AtomicInteger globalPlayerCount = new AtomicInteger();
|
||||||
private Future<?> integrityCheck;
|
private Future<?> integrityCheck;
|
||||||
private Future<?> heartbeatTask;
|
private Future<?> heartbeatTask;
|
||||||
private boolean usingLua;
|
|
||||||
private LuaManager.Script serverToPlayersScript;
|
private LuaManager.Script serverToPlayersScript;
|
||||||
private LuaManager.Script getPlayerCountScript;
|
private LuaManager.Script getPlayerCountScript;
|
||||||
|
|
||||||
@@ -75,28 +66,145 @@ public final class RedisBungee extends Plugin {
|
|||||||
.expireAfterWrite(5, TimeUnit.SECONDS)
|
.expireAfterWrite(5, TimeUnit.SECONDS)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch the {@link RedisBungeeAPI} object created on plugin start.
|
@Override
|
||||||
*
|
public RedisBungeeConfiguration getConfiguration() {
|
||||||
* @deprecated Please use {@link RedisBungeeAPI#getRedisBungeeApi()}
|
return this.configuration;
|
||||||
*
|
|
||||||
* @return the {@link RedisBungeeAPI} object instance.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public static RedisBungeeAPI getApi() {
|
|
||||||
return api;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PubSubListener getPubSubListener() {
|
@Override
|
||||||
return psl;
|
public int getCount() {
|
||||||
|
return this.globalPlayerCount.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
final List<String> getServerIds() {
|
@Override
|
||||||
|
public int getCurrentCount() {
|
||||||
|
Long count = (Long) getPlayerCountScript.eval(ImmutableList.<String>of(), ImmutableList.<String>of());
|
||||||
|
return count.intValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getLocalPlayersAsUuidStrings() {
|
||||||
|
ImmutableSet.Builder<String> builder = ImmutableSet.builder();
|
||||||
|
for (ProxiedPlayer player : getProxy().getPlayers()) {
|
||||||
|
builder.add(player.getUniqueId().toString());
|
||||||
|
}
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataManager<ProxiedPlayer, ?, ?, ?> getDataManager() {
|
||||||
|
return this.dataManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<UUID> getPlayers() {
|
||||||
|
ImmutableSet.Builder<UUID> setBuilder = ImmutableSet.builder();
|
||||||
|
if (isJedisAvailable()) {
|
||||||
|
try (Jedis rsc = requestJedis()) {
|
||||||
|
List<String> keys = new ArrayList<>();
|
||||||
|
for (String i : getServerIds()) {
|
||||||
|
keys.add("proxy:" + i + ":usersOnline");
|
||||||
|
}
|
||||||
|
if (!keys.isEmpty()) {
|
||||||
|
Set<String> users = rsc.sunion(keys.toArray(new String[keys.size()]));
|
||||||
|
if (users != null && !users.isEmpty()) {
|
||||||
|
for (String user : users) {
|
||||||
|
try {
|
||||||
|
setBuilder = setBuilder.add(UUID.fromString(user));
|
||||||
|
} catch (IllegalArgumentException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (JedisConnectionException e) {
|
||||||
|
// Redis server has disappeared!
|
||||||
|
getLogger().log(Level.SEVERE, "Unable to get connection from pool - did your Redis server go away?", e);
|
||||||
|
throw new RuntimeException("Unable to get all players online", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return setBuilder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Jedis requestJedis() {
|
||||||
|
return this.jedisPool.getResource();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isJedisAvailable() {
|
||||||
|
return !jedisPool.isClosed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JedisPool getJedisPool() {
|
||||||
|
return this.jedisPool;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RedisBungeeAPI getApi() {
|
||||||
|
return this.api;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UUIDTranslator getUuidTranslator() {
|
||||||
|
return this.uuidTranslator;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Multimap<String, UUID> serversToPlayers() {
|
||||||
|
try {
|
||||||
|
return serverToPlayersCache.get(SERVER_TO_PLAYERS_KEY, new Callable<Multimap<String, UUID>>() {
|
||||||
|
@Override
|
||||||
|
public Multimap<String, UUID> call() throws Exception {
|
||||||
|
Collection<String> data = (Collection<String>) serverToPlayersScript.eval(ImmutableList.<String>of(), getServerIds());
|
||||||
|
ImmutableMultimap.Builder<String, UUID> builder = ImmutableMultimap.builder();
|
||||||
|
String key = null;
|
||||||
|
for (String s : data) {
|
||||||
|
if (key == null) {
|
||||||
|
key = s;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.put(key, UUID.fromString(s));
|
||||||
|
key = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<UUID> getPlayersOnProxy(String proxyId) {
|
||||||
|
checkArgument(getServerIds().contains(proxyId), proxyId + " is not a valid proxy ID");
|
||||||
|
try (Jedis jedis = requestJedis()) {
|
||||||
|
Set<String> users = jedis.smembers("proxy:" + proxyId + ":usersOnline");
|
||||||
|
ImmutableSet.Builder<UUID> builder = ImmutableSet.builder();
|
||||||
|
for (String user : users) {
|
||||||
|
builder.add(UUID.fromString(user));
|
||||||
|
}
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendProxyCommand(String serverId, String command) {
|
||||||
|
checkArgument(getServerIds().contains(serverId) || serverId.equals("allservers"), "proxyId is invalid");
|
||||||
|
sendChannelMessage("redisbungee-" + serverId, command);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getServerIds() {
|
||||||
return serverIds;
|
return serverIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<String> getCurrentServerIds(boolean nag, boolean lagged) {
|
@Override
|
||||||
try (Jedis jedis = pool.getResource()) {
|
public List<String> getCurrentServerIds(boolean nag, boolean lagged) {
|
||||||
|
try (Jedis jedis = requestJedis()) {
|
||||||
long time = getRedisTime(jedis.time());
|
long time = getRedisTime(jedis.time());
|
||||||
int nagTime = 0;
|
int nagTime = 0;
|
||||||
if (nag) {
|
if (nag) {
|
||||||
@@ -126,97 +234,14 @@ public final class RedisBungee extends Plugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<UUID> getPlayersOnProxy(String server) {
|
|
||||||
checkArgument(getServerIds().contains(server), server + " is not a valid proxy ID");
|
|
||||||
try (Jedis jedis = pool.getResource()) {
|
|
||||||
Set<String> users = jedis.smembers("proxy:" + server + ":usersOnline");
|
|
||||||
ImmutableSet.Builder<UUID> builder = ImmutableSet.builder();
|
|
||||||
for (String user : users) {
|
|
||||||
builder.add(UUID.fromString(user));
|
|
||||||
}
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final Multimap<String, UUID> serversToPlayers() {
|
|
||||||
try {
|
|
||||||
return serverToPlayersCache.get(SERVER_TO_PLAYERS_KEY, new Callable<Multimap<String, UUID>>() {
|
|
||||||
@Override
|
@Override
|
||||||
public Multimap<String, UUID> call() throws Exception {
|
public PubSubListener getPubSubListener() {
|
||||||
Collection<String> data = (Collection<String>) serverToPlayersScript.eval(ImmutableList.<String>of(), getServerIds());
|
return this.psl;
|
||||||
|
|
||||||
ImmutableMultimap.Builder<String, UUID> builder = ImmutableMultimap.builder();
|
|
||||||
String key = null;
|
|
||||||
for (String s : data) {
|
|
||||||
if (key == null) {
|
|
||||||
key = s;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.put(key, UUID.fromString(s));
|
@Override
|
||||||
key = null;
|
public void sendChannelMessage(String channel, String message) {
|
||||||
}
|
try (Jedis jedis = requestJedis()) {
|
||||||
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (ExecutionException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final int getCount() {
|
|
||||||
return globalPlayerCount.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
final int getCurrentCount() {
|
|
||||||
Long count = (Long) getPlayerCountScript.eval(ImmutableList.<String>of(), ImmutableList.<String>of());
|
|
||||||
return count.intValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Set<String> getLocalPlayersAsUuidStrings() {
|
|
||||||
ImmutableSet.Builder<String> builder = ImmutableSet.builder();
|
|
||||||
for (ProxiedPlayer player : getProxy().getPlayers()) {
|
|
||||||
builder.add(player.getUniqueId().toString());
|
|
||||||
}
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
final Set<UUID> getPlayers() {
|
|
||||||
ImmutableSet.Builder<UUID> setBuilder = ImmutableSet.builder();
|
|
||||||
if (pool != null) {
|
|
||||||
try (Jedis rsc = pool.getResource()) {
|
|
||||||
List<String> keys = new ArrayList<>();
|
|
||||||
for (String i : getServerIds()) {
|
|
||||||
keys.add("proxy:" + i + ":usersOnline");
|
|
||||||
}
|
|
||||||
if (!keys.isEmpty()) {
|
|
||||||
Set<String> users = rsc.sunion(keys.toArray(new String[keys.size()]));
|
|
||||||
if (users != null && !users.isEmpty()) {
|
|
||||||
for (String user : users) {
|
|
||||||
try {
|
|
||||||
setBuilder = setBuilder.add(UUID.fromString(user));
|
|
||||||
} catch (IllegalArgumentException ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (JedisConnectionException e) {
|
|
||||||
// Redis server has disappeared!
|
|
||||||
getLogger().log(Level.SEVERE, "Unable to get connection from pool - did your Redis server go away?", e);
|
|
||||||
throw new RuntimeException("Unable to get all players online", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return setBuilder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
final void sendProxyCommand(@NonNull String proxyId, @NonNull String command) {
|
|
||||||
checkArgument(getServerIds().contains(proxyId) || proxyId.equals("allservers"), "proxyId is invalid");
|
|
||||||
sendChannelMessage("redisbungee-" + proxyId, command);
|
|
||||||
}
|
|
||||||
|
|
||||||
final void sendChannelMessage(String channel, String message) {
|
|
||||||
try (Jedis jedis = pool.getResource()) {
|
|
||||||
jedis.publish(channel, message);
|
jedis.publish(channel, message);
|
||||||
} catch (JedisConnectionException e) {
|
} catch (JedisConnectionException e) {
|
||||||
// Redis server has disappeared!
|
// Redis server has disappeared!
|
||||||
@@ -225,12 +250,90 @@ public final class RedisBungee extends Plugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private long getRedisTime(List<String> timeRes) {
|
@Override
|
||||||
return Long.parseLong(timeRes.get(0));
|
public void executeAsync(Runnable runnable) {
|
||||||
|
this.getProxy().getScheduler().runAsync(this, runnable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void executeAsyncAfter(Runnable runnable, TimeUnit timeUnit, int time) {
|
||||||
|
this.getProxy().getScheduler().schedule(this, runnable, time, timeUnit);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void callEvent(Object event) {
|
||||||
|
this.getProxy().getPluginManager().callEvent((Event) event);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isOnlineMode() {
|
||||||
|
return this.getProxy().getConfig().isOnlineMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void logInfo(String msg) {
|
||||||
|
this.getLogger().info(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void logWarn(String msg) {
|
||||||
|
this.getLogger().warning(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void logFatal(String msg) {
|
||||||
|
this.getLogger().severe(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ProxiedPlayer getPlayer(UUID uuid) {
|
||||||
|
return this.getProxy().getPlayer(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ProxiedPlayer getPlayer(String name) {
|
||||||
|
return this.getProxy().getPlayer(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UUID getPlayerUUID(String player) {
|
||||||
|
return this.getProxy().getPlayer(player).getUniqueId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPlayerName(UUID player) {
|
||||||
|
return this.getProxy().getPlayer(player).getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPlayerServerName(ProxiedPlayer player) {
|
||||||
|
return player.getServer().getInfo().getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPlayerOnAServer(ProxiedPlayer player) {
|
||||||
|
return player.getServer() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InetAddress getPlayerIp(ProxiedPlayer player) {
|
||||||
|
return player.getAddress().getAddress();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendProxyCommand(String cmd) {
|
||||||
|
checkArgument(getServerIds().contains(this.configuration.getServerId()) || this.configuration.getServerId().equals("allservers"), "proxyId is invalid");
|
||||||
|
sendChannelMessage("redisbungee-" + this.configuration.getServerId(), cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getRedisTime(List<String> timeRes) {
|
||||||
|
return Long.parseLong(timeRes.get(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void enable() {
|
||||||
ThreadFactory factory = ((ThreadPoolExecutor) getExecutorService()).getThreadFactory();
|
ThreadFactory factory = ((ThreadPoolExecutor) getExecutorService()).getThreadFactory();
|
||||||
ScheduledExecutorService service = Executors.newScheduledThreadPool(24, factory);
|
ScheduledExecutorService service = Executors.newScheduledThreadPool(24, factory);
|
||||||
try {
|
try {
|
||||||
@@ -250,15 +353,18 @@ public final class RedisBungee extends Plugin {
|
|||||||
} catch (JedisConnectionException e) {
|
} catch (JedisConnectionException e) {
|
||||||
throw new RuntimeException("Unable to connect to your Redis server!", e);
|
throw new RuntimeException("Unable to connect to your Redis server!", e);
|
||||||
}
|
}
|
||||||
if (pool != null) {
|
this.api = new RedisBungeeAPI(this);
|
||||||
try (Jedis tmpRsc = pool.getResource()) {
|
// call old plugin class to support old plugins
|
||||||
|
new RedisBungee(api);
|
||||||
|
if (isJedisAvailable()) {
|
||||||
|
try (Jedis tmpRsc = requestJedis()) {
|
||||||
// This is more portable than INFO <section>
|
// This is more portable than INFO <section>
|
||||||
String info = tmpRsc.info();
|
String info = tmpRsc.info();
|
||||||
for (String s : info.split("\r\n")) {
|
for (String s : info.split("\r\n")) {
|
||||||
if (s.startsWith("redis_version:")) {
|
if (s.startsWith("redis_version:")) {
|
||||||
String version = s.split(":")[1];
|
String version = s.split(":")[1];
|
||||||
getLogger().info(version + " <- redis version");
|
getLogger().info(version + " <- redis version");
|
||||||
if (!(usingLua = RedisUtil.canUseLua(version))) {
|
if (!RedisUtil.isRedisVersionRight(version)) {
|
||||||
getLogger().warning("Your version of Redis (" + version + ") is not at least version 6.0 RedisBungee requires a newer version of Redis.");
|
getLogger().warning("Your version of Redis (" + version + ") is not at least version 6.0 RedisBungee requires a newer version of Redis.");
|
||||||
throw new RuntimeException("Unsupported Redis version detected");
|
throw new RuntimeException("Unsupported Redis version detected");
|
||||||
} else {
|
} else {
|
||||||
@@ -282,7 +388,7 @@ public final class RedisBungee extends Plugin {
|
|||||||
heartbeatTask = service.scheduleAtFixedRate(new Runnable() {
|
heartbeatTask = service.scheduleAtFixedRate(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try (Jedis rsc = pool.getResource()) {
|
try (Jedis rsc = requestJedis()) {
|
||||||
long redisTime = getRedisTime(rsc.time());
|
long redisTime = getRedisTime(rsc.time());
|
||||||
rsc.hset("heartbeats", configuration.getServerId(), String.valueOf(redisTime));
|
rsc.hset("heartbeats", configuration.getServerId(), String.valueOf(redisTime));
|
||||||
} catch (JedisConnectionException e) {
|
} catch (JedisConnectionException e) {
|
||||||
@@ -298,28 +404,19 @@ public final class RedisBungee extends Plugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, 0, 3, TimeUnit.SECONDS);
|
}, 0, 3, TimeUnit.SECONDS);
|
||||||
dataManager = new DataManager(this);
|
dataManager = new BungeeDataManager(this);
|
||||||
if (configuration.isRegisterBungeeCommands()) {
|
// glist command
|
||||||
getProxy().getPluginManager().registerCommand(this, new RedisBungeeCommands.GlistCommand(this));
|
getProxy().getPluginManager().registerCommand(this, new RedisBungeeCommands.GlistCommand(this));
|
||||||
getProxy().getPluginManager().registerCommand(this, new RedisBungeeCommands.FindCommand(this));
|
|
||||||
getProxy().getPluginManager().registerCommand(this, new RedisBungeeCommands.LastSeenCommand(this));
|
|
||||||
getProxy().getPluginManager().registerCommand(this, new RedisBungeeCommands.IpCommand(this));
|
|
||||||
}
|
|
||||||
getProxy().getPluginManager().registerCommand(this, new RedisBungeeCommands.SendToAll(this));
|
|
||||||
getProxy().getPluginManager().registerCommand(this, new RedisBungeeCommands.ServerId(this));
|
|
||||||
getProxy().getPluginManager().registerCommand(this, new RedisBungeeCommands.ServerIds());
|
|
||||||
getProxy().getPluginManager().registerCommand(this, new RedisBungeeCommands.PlayerProxyCommand(this));
|
|
||||||
getProxy().getPluginManager().registerCommand(this, new RedisBungeeCommands.PlistCommand(this));
|
|
||||||
getProxy().getPluginManager().registerCommand(this, new RedisBungeeCommands.DebugCommand(this));
|
|
||||||
api = new RedisBungeeAPI(this);
|
|
||||||
getProxy().getPluginManager().registerListener(this, new RedisBungeeListener(this, configuration.getExemptAddresses()));
|
getProxy().getPluginManager().registerListener(this, new RedisBungeeListener(this, configuration.getExemptAddresses()));
|
||||||
getProxy().getPluginManager().registerListener(this, dataManager);
|
getProxy().getPluginManager().registerListener(this, dataManager);
|
||||||
psl = new PubSubListener();
|
psl = new PubSubListener(this);
|
||||||
getProxy().getScheduler().runAsync(this, psl);
|
getProxy().getScheduler().runAsync(this, psl);
|
||||||
integrityCheck = service.scheduleAtFixedRate(new Runnable() {
|
integrityCheck = service.scheduleAtFixedRate(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try (Jedis tmpRsc = pool.getResource()) {
|
try (Jedis tmpRsc = requestJedis()) {
|
||||||
Set<String> players = getLocalPlayersAsUuidStrings();
|
Set<String> players = getLocalPlayersAsUuidStrings();
|
||||||
Set<String> playersInRedis = tmpRsc.smembers("proxy:" + configuration.getServerId() + ":usersOnline");
|
Set<String> playersInRedis = tmpRsc.smembers("proxy:" + configuration.getServerId() + ":usersOnline");
|
||||||
List<String> lagged = getCurrentServerIds(false, true);
|
List<String> lagged = getCurrentServerIds(false, true);
|
||||||
@@ -370,7 +467,7 @@ public final class RedisBungee extends Plugin {
|
|||||||
if (proxiedPlayer == null)
|
if (proxiedPlayer == null)
|
||||||
continue; // We'll deal with it later.
|
continue; // We'll deal with it later.
|
||||||
|
|
||||||
RedisUtil.createPlayer(proxiedPlayer, pipeline, true);
|
RBUtils.createPlayer(proxiedPlayer, pipeline, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
pipeline.sync();
|
pipeline.sync();
|
||||||
@@ -385,15 +482,15 @@ public final class RedisBungee extends Plugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDisable() {
|
public void disable() {
|
||||||
if (pool != null) {
|
if (isJedisAvailable()) {
|
||||||
// Poison the PubSub listener
|
// Poison the PubSub listener
|
||||||
psl.poison();
|
psl.poison();
|
||||||
integrityCheck.cancel(true);
|
integrityCheck.cancel(true);
|
||||||
heartbeatTask.cancel(true);
|
heartbeatTask.cancel(true);
|
||||||
getProxy().getPluginManager().unregisterListeners(this);
|
getProxy().getPluginManager().unregisterListeners(this);
|
||||||
|
|
||||||
try (Jedis tmpRsc = pool.getResource()) {
|
try (Jedis tmpRsc = requestJedis()) {
|
||||||
tmpRsc.hdel("heartbeats", configuration.getServerId());
|
tmpRsc.hdel("heartbeats", configuration.getServerId());
|
||||||
if (tmpRsc.scard("proxy:" + configuration.getServerId() + ":usersOnline") > 0) {
|
if (tmpRsc.scard("proxy:" + configuration.getServerId() + ":usersOnline") > 0) {
|
||||||
Set<String> players = tmpRsc.smembers("proxy:" + configuration.getServerId() + ":usersOnline");
|
Set<String> players = tmpRsc.smembers("proxy:" + configuration.getServerId() + ":usersOnline");
|
||||||
@@ -402,11 +499,12 @@ public final class RedisBungee extends Plugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pool.destroy();
|
this.jedisPool.destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadConfig() throws IOException, JedisConnectionException {
|
@Override
|
||||||
|
public void loadConfig() throws IOException {
|
||||||
if (!getDataFolder().exists()) {
|
if (!getDataFolder().exists()) {
|
||||||
getDataFolder().mkdir();
|
getDataFolder().mkdir();
|
||||||
}
|
}
|
||||||
@@ -421,19 +519,23 @@ public final class RedisBungee extends Plugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final Configuration configuration = ConfigurationProvider.getProvider(YamlConfiguration.class).load(file);
|
final Configuration yamlConfiguration = ConfigurationProvider.getProvider(YamlConfiguration.class).load(file);
|
||||||
|
|
||||||
final String redisServer = configuration.getString("redis-server", "localhost");
|
final String redisServer = yamlConfiguration.getString("redis-server", "localhost");
|
||||||
final int redisPort = configuration.getInt("redis-port", 6379);
|
final int redisPort = yamlConfiguration.getInt("redis-port", 6379);
|
||||||
final boolean useSSL = configuration.getBoolean("useSSL");
|
final boolean useSSL = yamlConfiguration.getBoolean("useSSL", false);
|
||||||
String redisPassword = configuration.getString("redis-password");
|
String redisPassword = yamlConfiguration.getString("redis-password", "");
|
||||||
String serverId = configuration.getString("server-id");
|
String serverId = yamlConfiguration.getString("server-id");
|
||||||
final String randomUUID = UUID.randomUUID().toString();
|
final String randomUUID = UUID.randomUUID().toString();
|
||||||
|
|
||||||
|
// check redis password
|
||||||
if (redisPassword != null && (redisPassword.isEmpty() || redisPassword.equals("none"))) {
|
if (redisPassword != null && (redisPassword.isEmpty() || redisPassword.equals("none"))) {
|
||||||
redisPassword = null;
|
redisPassword = null;
|
||||||
|
getLogger().warning("INSECURE setup was detected Please set password for your redis instance.");
|
||||||
|
}
|
||||||
|
if (!useSSL) {
|
||||||
|
getLogger().warning("INSECURE setup was detected Please setup ssl for your redis instance.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configuration sanity checks.
|
// Configuration sanity checks.
|
||||||
if (serverId == null || serverId.isEmpty()) {
|
if (serverId == null || serverId.isEmpty()) {
|
||||||
/*
|
/*
|
||||||
@@ -442,38 +544,26 @@ public final class RedisBungee extends Plugin {
|
|||||||
*/
|
*/
|
||||||
String genId = UUID.randomUUID().toString();
|
String genId = UUID.randomUUID().toString();
|
||||||
getLogger().info("Generated server id " + genId + " and saving it to config.");
|
getLogger().info("Generated server id " + genId + " and saving it to config.");
|
||||||
configuration.set("server-id", genId);
|
yamlConfiguration.set("server-id", genId);
|
||||||
ConfigurationProvider.getProvider(YamlConfiguration.class).save(configuration, new File(getDataFolder(), "config.yml"));
|
ConfigurationProvider.getProvider(YamlConfiguration.class).save(yamlConfiguration, new File(getDataFolder(), "config.yml"));
|
||||||
|
getLogger().info("Server id was generated: " + serverId);
|
||||||
} else {
|
} else {
|
||||||
getLogger().info("Loaded server id " + serverId + '.');
|
getLogger().info("Loaded server id " + serverId + '.');
|
||||||
}
|
}
|
||||||
|
this.configuration = new RedisBungeeConfiguration(serverId, yamlConfiguration.getStringList("exempt-ip-addresses"));
|
||||||
if (configuration.getBoolean("use-random-id-string", false)) {
|
|
||||||
serverId = configuration.getString("server-id") + "-" + randomUUID;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (redisServer != null && !redisServer.isEmpty()) {
|
if (redisServer != null && !redisServer.isEmpty()) {
|
||||||
final String finalRedisPassword = redisPassword;
|
|
||||||
FutureTask<JedisPool> task = new FutureTask<>(new Callable<JedisPool>() {
|
|
||||||
@Override
|
|
||||||
public JedisPool call() throws Exception {
|
|
||||||
// Create the pool...
|
|
||||||
JedisPoolConfig config = new JedisPoolConfig();
|
|
||||||
config.setMaxTotal(configuration.getInt("max-redis-connections", 8));
|
|
||||||
return new JedisPool(config, redisServer, redisPort, 0, finalRedisPassword, useSSL);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
getProxy().getScheduler().runAsync(this, task);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
pool = task.get();
|
JedisPoolConfig config = new JedisPoolConfig();
|
||||||
} catch (InterruptedException | ExecutionException e) {
|
config.setMaxTotal(yamlConfiguration.getInt("max-redis-connections", 8));
|
||||||
|
this.jedisPool = new JedisPool(config, redisServer, redisPort, 0, redisPassword, useSSL);
|
||||||
|
|
||||||
|
} catch (JedisConnectionException e) {
|
||||||
throw new RuntimeException("Unable to create Redis pool", e);
|
throw new RuntimeException("Unable to create Redis pool", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test the connection
|
// Test the connection
|
||||||
try (Jedis rsc = pool.getResource()) {
|
try (Jedis rsc = requestJedis()) {
|
||||||
rsc.ping();
|
rsc.ping();
|
||||||
// If that worked, now we can check for an existing, alive Bungee:
|
// If that worked, now we can check for an existing, alive Bungee:
|
||||||
File crashFile = new File(getDataFolder(), "restarted_from_crash.txt");
|
File crashFile = new File(getDataFolder(), "restarted_from_crash.txt");
|
||||||
@@ -493,31 +583,17 @@ public final class RedisBungee extends Plugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FutureTask<Void> task2 = new FutureTask<>(new Callable<Void>() {
|
|
||||||
@Override
|
|
||||||
public Void call() throws Exception {
|
|
||||||
httpClient = new OkHttpClient();
|
httpClient = new OkHttpClient();
|
||||||
Dispatcher dispatcher = new Dispatcher(getExecutorService());
|
Dispatcher dispatcher = new Dispatcher(getExecutorService());
|
||||||
httpClient.setDispatcher(dispatcher);
|
httpClient.setDispatcher(dispatcher);
|
||||||
NameFetcher.setHttpClient(httpClient);
|
NameFetcher.setHttpClient(httpClient);
|
||||||
UUIDFetcher.setHttpClient(httpClient);
|
UUIDFetcher.setHttpClient(httpClient);
|
||||||
RedisBungee.configuration = new RedisBungeeConfiguration(RedisBungee.this.getPool(), configuration, randomUUID);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
getProxy().getScheduler().runAsync(this, task2);
|
|
||||||
|
|
||||||
try {
|
|
||||||
task2.get();
|
|
||||||
} catch (InterruptedException | ExecutionException e) {
|
|
||||||
throw new RuntimeException("Unable to create HTTP client", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
getLogger().log(Level.INFO, "Successfully connected to Redis.");
|
getLogger().log(Level.INFO, "Successfully connected to Redis.");
|
||||||
} catch (JedisConnectionException e) {
|
} catch (JedisConnectionException e) {
|
||||||
pool.destroy();
|
this.jedisPool.destroy();
|
||||||
pool = null;
|
this.jedisPool = null;
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -525,72 +601,33 @@ public final class RedisBungee extends Plugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
@Override
|
||||||
class PubSubListener implements Runnable {
|
public void onEnable() {
|
||||||
private JedisPubSubHandler jpsh;
|
enable();
|
||||||
|
}
|
||||||
private Set<String> addedChannels = new HashSet<String>();
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void onDisable() {
|
||||||
boolean broken = false;
|
disable();
|
||||||
try (Jedis rsc = pool.getResource()) {
|
|
||||||
try {
|
|
||||||
jpsh = new JedisPubSubHandler();
|
|
||||||
addedChannels.add("redisbungee-" + configuration.getServerId());
|
|
||||||
addedChannels.add("redisbungee-allservers");
|
|
||||||
addedChannels.add("redisbungee-data");
|
|
||||||
rsc.subscribe(jpsh, addedChannels.toArray(new String[0]));
|
|
||||||
} catch (Exception e) {
|
|
||||||
// FIXME: Extremely ugly hack
|
|
||||||
// Attempt to unsubscribe this instance and try again.
|
|
||||||
getLogger().log(Level.INFO, "PubSub error, attempting to recover.", e);
|
|
||||||
try {
|
|
||||||
jpsh.unsubscribe();
|
|
||||||
} catch (Exception e1) {
|
|
||||||
/* This may fail with
|
|
||||||
- java.net.SocketException: Broken pipe
|
|
||||||
- redis.clients.jedis.exceptions.JedisConnectionException: JedisPubSub was not subscribed to a Jedis instance
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
broken = true;
|
|
||||||
}
|
|
||||||
} catch (JedisConnectionException e) {
|
|
||||||
getLogger().log(Level.INFO, "PubSub error, attempting to recover in 5 secs.");
|
|
||||||
getProxy().getScheduler().schedule(RedisBungee.this, PubSubListener.this, 5, TimeUnit.SECONDS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (broken) {
|
|
||||||
run();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addChannel(String... channel) {
|
|
||||||
addedChannels.addAll(Arrays.asList(channel));
|
|
||||||
jpsh.subscribe(channel);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeChannel(String... channel) {
|
|
||||||
addedChannels.removeAll(Arrays.asList(channel));
|
|
||||||
jpsh.unsubscribe(channel);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void poison() {
|
|
||||||
addedChannels.clear();
|
|
||||||
jpsh.unsubscribe();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class JedisPubSubHandler extends JedisPubSub {
|
|
||||||
@Override
|
@Override
|
||||||
public void onMessage(final String s, final String s2) {
|
public Class<?> getPubSubEventClass() {
|
||||||
if (s2.trim().length() == 0) return;
|
return PubSubMessageEvent.class;
|
||||||
getProxy().getScheduler().runAsync(RedisBungee.this, new Runnable() {
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public Class<?> getNetworkJoinEventClass() {
|
||||||
getProxy().getPluginManager().callEvent(new PubSubMessageEvent(s, s2));
|
return PlayerJoinedNetworkEvent.class;
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
@Override
|
||||||
|
public Class<?> getServerChangeEventClass() {
|
||||||
|
return PlayerChangedServerNetworkEvent.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> getNetworkQuitEventClass() {
|
||||||
|
return PlayerJoinedNetworkEvent.class;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,49 +3,41 @@ package com.imaginarycode.minecraft.redisbungee;
|
|||||||
import com.google.common.base.Joiner;
|
import com.google.common.base.Joiner;
|
||||||
import com.google.common.collect.HashMultimap;
|
import com.google.common.collect.HashMultimap;
|
||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
import com.google.common.collect.Multiset;
|
|
||||||
import com.google.common.io.ByteArrayDataInput;
|
import com.google.common.io.ByteArrayDataInput;
|
||||||
import com.google.common.io.ByteArrayDataOutput;
|
import com.google.common.io.ByteArrayDataOutput;
|
||||||
import com.google.common.io.ByteStreams;
|
import com.google.common.io.ByteStreams;
|
||||||
|
import com.imaginarycode.minecraft.redisbungee.internal.AbstractRedisBungeeListener;
|
||||||
|
import com.imaginarycode.minecraft.redisbungee.internal.DataManager;
|
||||||
|
import com.imaginarycode.minecraft.redisbungee.internal.RedisBungeePlugin;
|
||||||
import com.imaginarycode.minecraft.redisbungee.events.PubSubMessageEvent;
|
import com.imaginarycode.minecraft.redisbungee.events.PubSubMessageEvent;
|
||||||
import com.imaginarycode.minecraft.redisbungee.util.RedisCallable;
|
import com.imaginarycode.minecraft.redisbungee.internal.RedisUtil;
|
||||||
import lombok.AllArgsConstructor;
|
import com.imaginarycode.minecraft.redisbungee.internal.util.RedisCallable;
|
||||||
import net.md_5.bungee.api.AbstractReconnectHandler;
|
import net.md_5.bungee.api.AbstractReconnectHandler;
|
||||||
import net.md_5.bungee.api.ChatColor;
|
|
||||||
import net.md_5.bungee.api.chat.BaseComponent;
|
|
||||||
import net.md_5.bungee.api.chat.ComponentBuilder;
|
|
||||||
import net.md_5.bungee.api.config.ServerInfo;
|
import net.md_5.bungee.api.config.ServerInfo;
|
||||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||||
import net.md_5.bungee.api.connection.Server;
|
import net.md_5.bungee.api.connection.Server;
|
||||||
import net.md_5.bungee.api.event.*;
|
import net.md_5.bungee.api.event.*;
|
||||||
import net.md_5.bungee.api.plugin.Listener;
|
import net.md_5.bungee.api.plugin.Listener;
|
||||||
|
import net.md_5.bungee.api.plugin.Plugin;
|
||||||
import net.md_5.bungee.event.EventHandler;
|
import net.md_5.bungee.event.EventHandler;
|
||||||
import net.md_5.bungee.event.EventPriority;
|
|
||||||
import redis.clients.jedis.Jedis;
|
import redis.clients.jedis.Jedis;
|
||||||
import redis.clients.jedis.Pipeline;
|
import redis.clients.jedis.Pipeline;
|
||||||
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@AllArgsConstructor
|
public class RedisBungeeListener extends AbstractRedisBungeeListener<LoginEvent, PostLoginEvent, PlayerDisconnectEvent, ServerConnectedEvent, ProxyPingEvent, PluginMessageEvent, PubSubMessageEvent> implements Listener {
|
||||||
public class RedisBungeeListener implements Listener {
|
|
||||||
private static final BaseComponent[] ALREADY_LOGGED_IN =
|
|
||||||
new ComponentBuilder("You are already logged on to this server.").color(ChatColor.RED)
|
|
||||||
.append("\n\nIt may help to try logging in again in a few minutes.\nIf this does not resolve your issue, please contact staff.")
|
|
||||||
.color(ChatColor.GRAY)
|
|
||||||
.create();
|
|
||||||
private static final BaseComponent[] ONLINE_MODE_RECONNECT =
|
|
||||||
new ComponentBuilder("Whoops! You need to reconnect.").color(ChatColor.RED)
|
|
||||||
.append("\n\nWe found someone online using your username. They were kicked and you may reconnect.\nIf this does not work, please contact staff.")
|
|
||||||
.color(ChatColor.GRAY)
|
|
||||||
.create();
|
|
||||||
private final RedisBungee plugin;
|
|
||||||
private final List<InetAddress> exemptAddresses;
|
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.LOWEST)
|
|
||||||
public void onLogin(final LoginEvent event) {
|
public RedisBungeeListener(RedisBungeePlugin<?> plugin, List<InetAddress> exemptAddresses) {
|
||||||
event.registerIntent(plugin);
|
super(plugin, exemptAddresses);
|
||||||
plugin.getProxy().getScheduler().runAsync(plugin, new RedisCallable<Void>(plugin) {
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@EventHandler
|
||||||
|
public void onLogin(LoginEvent event) {
|
||||||
|
event.registerIntent((Plugin) plugin);
|
||||||
|
plugin.executeAsync(new RedisCallable<Void>(plugin) {
|
||||||
@Override
|
@Override
|
||||||
protected Void call(Jedis jedis) {
|
protected Void call(Jedis jedis) {
|
||||||
try {
|
try {
|
||||||
@@ -55,8 +47,8 @@ public class RedisBungeeListener implements Listener {
|
|||||||
|
|
||||||
// We make sure they aren't trying to use an existing player's name.
|
// We make sure they aren't trying to use an existing player's name.
|
||||||
// This is problematic for online-mode servers as they always disconnect old clients.
|
// This is problematic for online-mode servers as they always disconnect old clients.
|
||||||
if (plugin.getProxy().getConfig().isOnlineMode()) {
|
if (plugin.isOnlineMode()) {
|
||||||
ProxiedPlayer player = plugin.getProxy().getPlayer(event.getConnection().getName());
|
ProxiedPlayer player = (ProxiedPlayer) plugin.getPlayer(event.getConnection().getName());
|
||||||
|
|
||||||
if (player != null) {
|
if (player != null) {
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
@@ -76,15 +68,16 @@ public class RedisBungeeListener implements Listener {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
} finally {
|
} finally {
|
||||||
event.completeIntent(plugin);
|
event.completeIntent((Plugin) plugin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onPostLogin(final PostLoginEvent event) {
|
public void onPostLogin(PostLoginEvent event) {
|
||||||
plugin.getProxy().getScheduler().runAsync(plugin, new RedisCallable<Void>(plugin) {
|
plugin.executeAsync(new RedisCallable<Void>(plugin) {
|
||||||
@Override
|
@Override
|
||||||
protected Void call(Jedis jedis) {
|
protected Void call(Jedis jedis) {
|
||||||
// this code was moved out from login event due being async..
|
// this code was moved out from login event due being async..
|
||||||
@@ -92,21 +85,22 @@ public class RedisBungeeListener implements Listener {
|
|||||||
// which will register the player into the redis database.
|
// which will register the player into the redis database.
|
||||||
Pipeline pipeline = jedis.pipelined();
|
Pipeline pipeline = jedis.pipelined();
|
||||||
plugin.getUuidTranslator().persistInfo(event.getPlayer().getName(), event.getPlayer().getUniqueId(), pipeline);
|
plugin.getUuidTranslator().persistInfo(event.getPlayer().getName(), event.getPlayer().getUniqueId(), pipeline);
|
||||||
RedisUtil.createPlayer(event.getPlayer(), pipeline, false);
|
RBUtils.createPlayer(event.getPlayer(), pipeline, false);
|
||||||
pipeline.sync();
|
pipeline.sync();
|
||||||
// the end of moved code.
|
// the end of moved code.
|
||||||
|
|
||||||
jedis.publish("redisbungee-data", RedisBungee.getGson().toJson(new DataManager.DataManagerMessage<>(
|
jedis.publish("redisbungee-data", gson.toJson(new DataManager.DataManagerMessage(
|
||||||
event.getPlayer().getUniqueId(), DataManager.DataManagerMessage.Action.JOIN,
|
event.getPlayer().getUniqueId(), plugin.getApi().getServerId(), DataManager.DataManagerMessage.Action.JOIN,
|
||||||
new DataManager.LoginPayload(event.getPlayer().getAddress().getAddress()))));
|
new DataManager.LoginPayload(event.getPlayer().getAddress().getAddress()))));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onPlayerDisconnect(final PlayerDisconnectEvent event) {
|
public void onPlayerDisconnect(PlayerDisconnectEvent event) {
|
||||||
plugin.getProxy().getScheduler().runAsync(plugin, new RedisCallable<Void>(plugin) {
|
plugin.executeAsync(new RedisCallable<Void>(plugin) {
|
||||||
@Override
|
@Override
|
||||||
protected Void call(Jedis jedis) {
|
protected Void call(Jedis jedis) {
|
||||||
Pipeline pipeline = jedis.pipelined();
|
Pipeline pipeline = jedis.pipelined();
|
||||||
@@ -115,45 +109,47 @@ public class RedisBungeeListener implements Listener {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onServerChange(final ServerConnectedEvent event) {
|
public void onServerChange(ServerConnectedEvent event) {
|
||||||
final String currentServer = event.getPlayer().getServer() == null ? null : event.getPlayer().getServer().getInfo().getName();
|
final String currentServer = event.getPlayer().getServer() == null ? null : event.getPlayer().getServer().getInfo().getName();
|
||||||
plugin.getProxy().getScheduler().runAsync(plugin, new RedisCallable<Void>(plugin) {
|
plugin.executeAsync(new RedisCallable<Void>(plugin) {
|
||||||
@Override
|
@Override
|
||||||
protected Void call(Jedis jedis) {
|
protected Void call(Jedis jedis) {
|
||||||
jedis.hset("player:" + event.getPlayer().getUniqueId().toString(), "server", event.getServer().getInfo().getName());
|
jedis.hset("player:" + event.getPlayer().getUniqueId().toString(), "server", event.getServer().getInfo().getName());
|
||||||
jedis.publish("redisbungee-data", RedisBungee.getGson().toJson(new DataManager.DataManagerMessage<>(
|
jedis.publish("redisbungee-data", gson.toJson(new DataManager.DataManagerMessage(
|
||||||
event.getPlayer().getUniqueId(), DataManager.DataManagerMessage.Action.SERVER_CHANGE,
|
event.getPlayer().getUniqueId(), plugin.getApi().getServerId(), DataManager.DataManagerMessage.Action.SERVER_CHANGE,
|
||||||
new DataManager.ServerChangePayload(event.getServer().getInfo().getName(), currentServer))));
|
new DataManager.ServerChangePayload(event.getServer().getInfo().getName(), currentServer))));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.LOWEST)
|
@Override
|
||||||
public void onPing(final ProxyPingEvent event) {
|
@EventHandler
|
||||||
|
public void onPing(ProxyPingEvent event) {
|
||||||
if (exemptAddresses.contains(event.getConnection().getAddress().getAddress())) {
|
if (exemptAddresses.contains(event.getConnection().getAddress().getAddress())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ServerInfo forced = AbstractReconnectHandler.getForcedHost(event.getConnection());
|
ServerInfo forced = AbstractReconnectHandler.getForcedHost(event.getConnection());
|
||||||
|
|
||||||
if (forced != null && event.getConnection().getListener().isPingPassthrough()) {
|
if (forced != null && event.getConnection().getListener().isPingPassthrough()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
event.getResponse().getPlayers().setOnline(plugin.getCount());
|
event.getResponse().getPlayers().setOnline(plugin.getCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
@SuppressWarnings("UnstableApiUsage")
|
@SuppressWarnings("UnstableApiUsage")
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onPluginMessage(final PluginMessageEvent event) {
|
public void onPluginMessage(PluginMessageEvent event) {
|
||||||
if ((event.getTag().equals("legacy:redisbungee") || event.getTag().equals("RedisBungee")) && event.getSender() instanceof Server) {
|
if ((event.getTag().equals("legacy:redisbungee") || event.getTag().equals("RedisBungee")) && event.getSender() instanceof Server) {
|
||||||
final String currentChannel = event.getTag();
|
final String currentChannel = event.getTag();
|
||||||
final byte[] data = Arrays.copyOf(event.getData(), event.getData().length);
|
final byte[] data = Arrays.copyOf(event.getData(), event.getData().length);
|
||||||
plugin.getProxy().getScheduler().runAsync(plugin, () -> {
|
plugin.executeAsync(() -> {
|
||||||
ByteArrayDataInput in = ByteStreams.newDataInput(data);
|
ByteArrayDataInput in = ByteStreams.newDataInput(data);
|
||||||
|
|
||||||
String subchannel = in.readUTF();
|
String subchannel = in.readUTF();
|
||||||
@@ -170,7 +166,7 @@ public class RedisBungeeListener implements Listener {
|
|||||||
original = plugin.getPlayers();
|
original = plugin.getPlayers();
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
original = RedisBungee.getApi().getPlayersOnServer(type);
|
original = plugin.getApi().getPlayersOnServer(type);
|
||||||
} catch (IllegalArgumentException ignored) {
|
} catch (IllegalArgumentException ignored) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -188,7 +184,7 @@ public class RedisBungeeListener implements Listener {
|
|||||||
} else {
|
} else {
|
||||||
out.writeUTF(type);
|
out.writeUTF(type);
|
||||||
try {
|
try {
|
||||||
out.writeInt(RedisBungee.getApi().getPlayersOnServer(type).size());
|
out.writeInt(plugin.getApi().getPlayersOnServer(type).size());
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
out.writeInt(0);
|
out.writeInt(0);
|
||||||
}
|
}
|
||||||
@@ -198,12 +194,12 @@ public class RedisBungeeListener implements Listener {
|
|||||||
String user = in.readUTF();
|
String user = in.readUTF();
|
||||||
out.writeUTF("LastOnline");
|
out.writeUTF("LastOnline");
|
||||||
out.writeUTF(user);
|
out.writeUTF(user);
|
||||||
out.writeLong(RedisBungee.getApi().getLastOnline(plugin.getUuidTranslator().getTranslatedUuid(user, true)));
|
out.writeLong(plugin.getApi().getLastOnline(plugin.getUuidTranslator().getTranslatedUuid(user, true)));
|
||||||
break;
|
break;
|
||||||
case "ServerPlayers":
|
case "ServerPlayers":
|
||||||
String type1 = in.readUTF();
|
String type1 = in.readUTF();
|
||||||
out.writeUTF("ServerPlayers");
|
out.writeUTF("ServerPlayers");
|
||||||
Multimap<String, UUID> multimap = RedisBungee.getApi().getServerToPlayers();
|
Multimap<String, UUID> multimap = plugin.getApi().getServerToPlayers();
|
||||||
|
|
||||||
boolean includesUsers;
|
boolean includesUsers;
|
||||||
|
|
||||||
@@ -233,13 +229,13 @@ public class RedisBungeeListener implements Listener {
|
|||||||
break;
|
break;
|
||||||
case "Proxy":
|
case "Proxy":
|
||||||
out.writeUTF("Proxy");
|
out.writeUTF("Proxy");
|
||||||
out.writeUTF(RedisBungee.getConfiguration().getServerId());
|
out.writeUTF(plugin.getConfiguration().getServerId());
|
||||||
break;
|
break;
|
||||||
case "PlayerProxy":
|
case "PlayerProxy":
|
||||||
String username = in.readUTF();
|
String username = in.readUTF();
|
||||||
out.writeUTF("PlayerProxy");
|
out.writeUTF("PlayerProxy");
|
||||||
out.writeUTF(username);
|
out.writeUTF(username);
|
||||||
out.writeUTF(RedisBungee.getApi().getProxy(plugin.getUuidTranslator().getTranslatedUuid(username, true)));
|
out.writeUTF(plugin.getApi().getProxy(plugin.getUuidTranslator().getTranslatedUuid(username, true)));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
@@ -250,42 +246,15 @@ public class RedisBungeeListener implements Listener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void serializeMultiset(Multiset<String> collection, ByteArrayDataOutput output) {
|
@Override
|
||||||
output.writeInt(collection.elementSet().size());
|
|
||||||
for (Multiset.Entry<String> entry : collection.entrySet()) {
|
|
||||||
output.writeUTF(entry.getElement());
|
|
||||||
output.writeInt(entry.getCount());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("SameParameterValue")
|
|
||||||
private void serializeMultimap(Multimap<String, String> collection, boolean includeNames, ByteArrayDataOutput output) {
|
|
||||||
output.writeInt(collection.keySet().size());
|
|
||||||
for (Map.Entry<String, Collection<String>> entry : collection.asMap().entrySet()) {
|
|
||||||
output.writeUTF(entry.getKey());
|
|
||||||
if (includeNames) {
|
|
||||||
serializeCollection(entry.getValue(), output);
|
|
||||||
} else {
|
|
||||||
output.writeInt(entry.getValue().size());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void serializeCollection(Collection<?> collection, ByteArrayDataOutput output) {
|
|
||||||
output.writeInt(collection.size());
|
|
||||||
for (Object o : collection) {
|
|
||||||
output.writeUTF(o.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onPubSubMessage(PubSubMessageEvent event) {
|
public void onPubSubMessage(PubSubMessageEvent event) {
|
||||||
if (event.getChannel().equals("redisbungee-allservers") || event.getChannel().equals("redisbungee-" + RedisBungee.getApi().getServerId())) {
|
if (event.getChannel().equals("redisbungee-allservers") || event.getChannel().equals("redisbungee-" + plugin.getApi().getServerId())) {
|
||||||
String message = event.getMessage();
|
String message = event.getMessage();
|
||||||
if (message.startsWith("/"))
|
if (message.startsWith("/"))
|
||||||
message = message.substring(1);
|
message = message.substring(1);
|
||||||
plugin.getLogger().info("Invoking command via PubSub: /" + message);
|
plugin.logInfo("Invoking command via PubSub: /" + message);
|
||||||
plugin.getProxy().getPluginManager().dispatchCommand(RedisBungeeCommandSender.instance, message);
|
plugin.sendProxyCommand(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
package com.imaginarycode.minecraft.redisbungee.commands;
|
||||||
|
|
||||||
|
import com.google.common.base.Joiner;
|
||||||
|
import com.google.common.collect.HashMultimap;
|
||||||
|
import com.google.common.collect.Multimap;
|
||||||
|
import com.imaginarycode.minecraft.redisbungee.RedisBungeeAPI;
|
||||||
|
import com.imaginarycode.minecraft.redisbungee.internal.RedisBungeePlugin;
|
||||||
|
import net.md_5.bungee.api.ChatColor;
|
||||||
|
import net.md_5.bungee.api.CommandSender;
|
||||||
|
import net.md_5.bungee.api.chat.BaseComponent;
|
||||||
|
import net.md_5.bungee.api.chat.ComponentBuilder;
|
||||||
|
import net.md_5.bungee.api.chat.TextComponent;
|
||||||
|
import net.md_5.bungee.api.plugin.Command;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.TreeSet;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class contains subclasses that are used for the commands RedisBungee overrides or includes: /glist, /find and /lastseen.
|
||||||
|
* <p>
|
||||||
|
* All classes use the {@link RedisBungeeAPI}.
|
||||||
|
*
|
||||||
|
* @author tuxed
|
||||||
|
* @since 0.2.3
|
||||||
|
*/
|
||||||
|
public class RedisBungeeCommands {
|
||||||
|
|
||||||
|
private static String playerPlural(int num) {
|
||||||
|
return num == 1 ? num + " player is" : num + " players are";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class GlistCommand extends Command {
|
||||||
|
private final RedisBungeePlugin<?> plugin;
|
||||||
|
|
||||||
|
public GlistCommand(RedisBungeePlugin<?> plugin) {
|
||||||
|
super("glist", "bungeecord.command.list", "redisbungee", "rglist");
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(final CommandSender sender, final String[] args) {
|
||||||
|
plugin.executeAsync(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
int count = plugin.getApi().getPlayerCount();
|
||||||
|
BaseComponent[] playersOnline = new ComponentBuilder("").color(ChatColor.YELLOW)
|
||||||
|
.append(playerPlural(count) + " currently online.").create();
|
||||||
|
if (args.length > 0 && args[0].equals("showall")) {
|
||||||
|
Multimap<String, UUID> serverToPlayers = plugin.getApi().getServerToPlayers();
|
||||||
|
Multimap<String, String> human = HashMultimap.create();
|
||||||
|
for (Map.Entry<String, UUID> entry : serverToPlayers.entries()) {
|
||||||
|
human.put(entry.getKey(), plugin.getUuidTranslator().getNameFromUuid(entry.getValue(), false));
|
||||||
|
}
|
||||||
|
for (String server : new TreeSet<>(serverToPlayers.keySet())) {
|
||||||
|
TextComponent serverName = new TextComponent();
|
||||||
|
serverName.setColor(ChatColor.GREEN);
|
||||||
|
serverName.setText("[" + server + "] ");
|
||||||
|
TextComponent serverCount = new TextComponent();
|
||||||
|
serverCount.setColor(ChatColor.YELLOW);
|
||||||
|
serverCount.setText("(" + serverToPlayers.get(server).size() + "): ");
|
||||||
|
TextComponent serverPlayers = new TextComponent();
|
||||||
|
serverPlayers.setColor(ChatColor.WHITE);
|
||||||
|
serverPlayers.setText(Joiner.on(", ").join(human.get(server)));
|
||||||
|
sender.sendMessage(serverName, serverCount, serverPlayers);
|
||||||
|
}
|
||||||
|
sender.sendMessage(playersOnline);
|
||||||
|
} else {
|
||||||
|
sender.sendMessage(playersOnline);
|
||||||
|
sender.sendMessage(new ComponentBuilder("To see all players online, use /glist showall.").color(ChatColor.YELLOW).create());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
name: ${project.name}
|
name: RedisBungee
|
||||||
main: com.imaginarycode.minecraft.redisbungee.RedisBungee
|
main: com.imaginarycode.minecraft.redisbungee.RedisBungeeBungeePlugin
|
||||||
version: ${project.version}
|
version: ${project.version}
|
||||||
author: Chunkr and Govindas limework
|
author: Chunkr and Govindas limework
|
||||||
authors:
|
authors:
|
||||||
52
RedisBungee-BungeeEvents/pom.xml
Normal file
52
RedisBungee-BungeeEvents/pom.xml
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<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">
|
||||||
|
<parent>
|
||||||
|
<artifactId>RedisBungee</artifactId>
|
||||||
|
<groupId>com.imaginarycode.minecraft</groupId>
|
||||||
|
<version>0.7.2-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>RedisBungee-BungeeEvents</artifactId>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>8</maven.compiler.target>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>bungeecord-repo</id>
|
||||||
|
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
|
<version>3.3.2</version>
|
||||||
|
<configuration>
|
||||||
|
<source>8</source>
|
||||||
|
<reportOutputDirectory>../javadoc</reportOutputDirectory>
|
||||||
|
<destDir>${project.name}</destDir>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.md-5</groupId>
|
||||||
|
<artifactId>bungeecord-api</artifactId>
|
||||||
|
<version>1.17-R0.1-SNAPSHOT</version>
|
||||||
|
<type>jar</type>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
|
||||||
|
</project>
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
package com.imaginarycode.minecraft.redisbungee.events;
|
package com.imaginarycode.minecraft.redisbungee.events;
|
||||||
|
|
||||||
import lombok.ToString;
|
|
||||||
import net.md_5.bungee.api.plugin.Event;
|
import net.md_5.bungee.api.plugin.Event;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
@@ -14,7 +13,6 @@ import java.util.UUID;
|
|||||||
*
|
*
|
||||||
* @since 0.3.4
|
* @since 0.3.4
|
||||||
*/
|
*/
|
||||||
@ToString
|
|
||||||
public class PlayerChangedServerNetworkEvent extends Event {
|
public class PlayerChangedServerNetworkEvent extends Event {
|
||||||
private final UUID uuid;
|
private final UUID uuid;
|
||||||
private final String previousServer;
|
private final String previousServer;
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
package com.imaginarycode.minecraft.redisbungee.events;
|
package com.imaginarycode.minecraft.redisbungee.events;
|
||||||
|
|
||||||
import lombok.ToString;
|
|
||||||
import net.md_5.bungee.api.plugin.Event;
|
import net.md_5.bungee.api.plugin.Event;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
@@ -14,7 +13,6 @@ import java.util.UUID;
|
|||||||
*
|
*
|
||||||
* @since 0.3.4
|
* @since 0.3.4
|
||||||
*/
|
*/
|
||||||
@ToString
|
|
||||||
public class PlayerJoinedNetworkEvent extends Event {
|
public class PlayerJoinedNetworkEvent extends Event {
|
||||||
private final UUID uuid;
|
private final UUID uuid;
|
||||||
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
package com.imaginarycode.minecraft.redisbungee.events;
|
package com.imaginarycode.minecraft.redisbungee.events;
|
||||||
|
|
||||||
import lombok.ToString;
|
|
||||||
import net.md_5.bungee.api.plugin.Event;
|
import net.md_5.bungee.api.plugin.Event;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
@@ -14,7 +13,6 @@ import java.util.UUID;
|
|||||||
*
|
*
|
||||||
* @since 0.3.4
|
* @since 0.3.4
|
||||||
*/
|
*/
|
||||||
@ToString
|
|
||||||
public class PlayerLeftNetworkEvent extends Event {
|
public class PlayerLeftNetworkEvent extends Event {
|
||||||
private final UUID uuid;
|
private final UUID uuid;
|
||||||
|
|
||||||
@@ -1,7 +1,5 @@
|
|||||||
package com.imaginarycode.minecraft.redisbungee.events;
|
package com.imaginarycode.minecraft.redisbungee.events;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.ToString;
|
|
||||||
import net.md_5.bungee.api.plugin.Event;
|
import net.md_5.bungee.api.plugin.Event;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -11,12 +9,16 @@ import net.md_5.bungee.api.plugin.Event;
|
|||||||
*
|
*
|
||||||
* @since 0.2.6
|
* @since 0.2.6
|
||||||
*/
|
*/
|
||||||
@RequiredArgsConstructor
|
|
||||||
@ToString
|
|
||||||
public class PubSubMessageEvent extends Event {
|
public class PubSubMessageEvent extends Event {
|
||||||
private final String channel;
|
private final String channel;
|
||||||
private final String message;
|
private final String message;
|
||||||
|
|
||||||
|
public PubSubMessageEvent(String channel, String message) {
|
||||||
|
this.channel = channel;
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
public String getChannel() {
|
public String getChannel() {
|
||||||
return channel;
|
return channel;
|
||||||
}
|
}
|
||||||
3
makeJavadocs.sh
Normal file
3
makeJavadocs.sh
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
rm -rf javadoc
|
||||||
|
mkdir javadoc
|
||||||
|
mvn javadoc:javadoc -pl RedisBungee-API,RedisBungee-BungeeEvents -am
|
||||||
310
mvnw
vendored
310
mvnw
vendored
@@ -1,310 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
# ----------------------------------------------------------------------------
|
|
||||||
# Licensed to the Apache Software Foundation (ASF) under one
|
|
||||||
# or more contributor license agreements. See the NOTICE file
|
|
||||||
# distributed with this work for additional information
|
|
||||||
# regarding copyright ownership. The ASF licenses this file
|
|
||||||
# to you 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.
|
|
||||||
# ----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------------------
|
|
||||||
# Maven Start Up Batch script
|
|
||||||
#
|
|
||||||
# Required ENV vars:
|
|
||||||
# ------------------
|
|
||||||
# JAVA_HOME - location of a JDK home dir
|
|
||||||
#
|
|
||||||
# Optional ENV vars
|
|
||||||
# -----------------
|
|
||||||
# M2_HOME - location of maven2's installed home dir
|
|
||||||
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
|
||||||
# e.g. to debug Maven itself, use
|
|
||||||
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
|
||||||
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
|
||||||
# ----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
if [ -z "$MAVEN_SKIP_RC" ] ; then
|
|
||||||
|
|
||||||
if [ -f /etc/mavenrc ] ; then
|
|
||||||
. /etc/mavenrc
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -f "$HOME/.mavenrc" ] ; then
|
|
||||||
. "$HOME/.mavenrc"
|
|
||||||
fi
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
# OS specific support. $var _must_ be set to either true or false.
|
|
||||||
cygwin=false;
|
|
||||||
darwin=false;
|
|
||||||
mingw=false
|
|
||||||
case "`uname`" in
|
|
||||||
CYGWIN*) cygwin=true ;;
|
|
||||||
MINGW*) mingw=true;;
|
|
||||||
Darwin*) darwin=true
|
|
||||||
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
|
|
||||||
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
|
|
||||||
if [ -z "$JAVA_HOME" ]; then
|
|
||||||
if [ -x "/usr/libexec/java_home" ]; then
|
|
||||||
export JAVA_HOME="`/usr/libexec/java_home`"
|
|
||||||
else
|
|
||||||
export JAVA_HOME="/Library/Java/Home"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
if [ -z "$JAVA_HOME" ] ; then
|
|
||||||
if [ -r /etc/gentoo-release ] ; then
|
|
||||||
JAVA_HOME=`java-config --jre-home`
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$M2_HOME" ] ; then
|
|
||||||
## resolve links - $0 may be a link to maven's home
|
|
||||||
PRG="$0"
|
|
||||||
|
|
||||||
# need this for relative symlinks
|
|
||||||
while [ -h "$PRG" ] ; do
|
|
||||||
ls=`ls -ld "$PRG"`
|
|
||||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
|
||||||
if expr "$link" : '/.*' > /dev/null; then
|
|
||||||
PRG="$link"
|
|
||||||
else
|
|
||||||
PRG="`dirname "$PRG"`/$link"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
saveddir=`pwd`
|
|
||||||
|
|
||||||
M2_HOME=`dirname "$PRG"`/..
|
|
||||||
|
|
||||||
# make it fully qualified
|
|
||||||
M2_HOME=`cd "$M2_HOME" && pwd`
|
|
||||||
|
|
||||||
cd "$saveddir"
|
|
||||||
# echo Using m2 at $M2_HOME
|
|
||||||
fi
|
|
||||||
|
|
||||||
# For Cygwin, ensure paths are in UNIX format before anything is touched
|
|
||||||
if $cygwin ; then
|
|
||||||
[ -n "$M2_HOME" ] &&
|
|
||||||
M2_HOME=`cygpath --unix "$M2_HOME"`
|
|
||||||
[ -n "$JAVA_HOME" ] &&
|
|
||||||
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
|
||||||
[ -n "$CLASSPATH" ] &&
|
|
||||||
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
|
|
||||||
fi
|
|
||||||
|
|
||||||
# For Mingw, ensure paths are in UNIX format before anything is touched
|
|
||||||
if $mingw ; then
|
|
||||||
[ -n "$M2_HOME" ] &&
|
|
||||||
M2_HOME="`(cd "$M2_HOME"; pwd)`"
|
|
||||||
[ -n "$JAVA_HOME" ] &&
|
|
||||||
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$JAVA_HOME" ]; then
|
|
||||||
javaExecutable="`which javac`"
|
|
||||||
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
|
|
||||||
# readlink(1) is not available as standard on Solaris 10.
|
|
||||||
readLink=`which readlink`
|
|
||||||
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
|
|
||||||
if $darwin ; then
|
|
||||||
javaHome="`dirname \"$javaExecutable\"`"
|
|
||||||
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
|
|
||||||
else
|
|
||||||
javaExecutable="`readlink -f \"$javaExecutable\"`"
|
|
||||||
fi
|
|
||||||
javaHome="`dirname \"$javaExecutable\"`"
|
|
||||||
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
|
|
||||||
JAVA_HOME="$javaHome"
|
|
||||||
export JAVA_HOME
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$JAVACMD" ] ; then
|
|
||||||
if [ -n "$JAVA_HOME" ] ; then
|
|
||||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
|
||||||
# IBM's JDK on AIX uses strange locations for the executables
|
|
||||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
|
||||||
else
|
|
||||||
JAVACMD="$JAVA_HOME/bin/java"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
JAVACMD="`which java`"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -x "$JAVACMD" ] ; then
|
|
||||||
echo "Error: JAVA_HOME is not defined correctly." >&2
|
|
||||||
echo " We cannot execute $JAVACMD" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$JAVA_HOME" ] ; then
|
|
||||||
echo "Warning: JAVA_HOME environment variable is not set."
|
|
||||||
fi
|
|
||||||
|
|
||||||
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
|
|
||||||
|
|
||||||
# traverses directory structure from process work directory to filesystem root
|
|
||||||
# first directory with .mvn subdirectory is considered project base directory
|
|
||||||
find_maven_basedir() {
|
|
||||||
|
|
||||||
if [ -z "$1" ]
|
|
||||||
then
|
|
||||||
echo "Path not specified to find_maven_basedir"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
basedir="$1"
|
|
||||||
wdir="$1"
|
|
||||||
while [ "$wdir" != '/' ] ; do
|
|
||||||
if [ -d "$wdir"/.mvn ] ; then
|
|
||||||
basedir=$wdir
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
|
|
||||||
if [ -d "${wdir}" ]; then
|
|
||||||
wdir=`cd "$wdir/.."; pwd`
|
|
||||||
fi
|
|
||||||
# end of workaround
|
|
||||||
done
|
|
||||||
echo "${basedir}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# concatenates all lines of a file
|
|
||||||
concat_lines() {
|
|
||||||
if [ -f "$1" ]; then
|
|
||||||
echo "$(tr -s '\n' ' ' < "$1")"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
BASE_DIR=`find_maven_basedir "$(pwd)"`
|
|
||||||
if [ -z "$BASE_DIR" ]; then
|
|
||||||
exit 1;
|
|
||||||
fi
|
|
||||||
|
|
||||||
##########################################################################################
|
|
||||||
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
|
|
||||||
# This allows using the maven wrapper in projects that prohibit checking in binary data.
|
|
||||||
##########################################################################################
|
|
||||||
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
|
|
||||||
if [ "$MVNW_VERBOSE" = true ]; then
|
|
||||||
echo "Found .mvn/wrapper/maven-wrapper.jar"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
if [ "$MVNW_VERBOSE" = true ]; then
|
|
||||||
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
|
|
||||||
fi
|
|
||||||
if [ -n "$MVNW_REPOURL" ]; then
|
|
||||||
jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
|
|
||||||
else
|
|
||||||
jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
|
|
||||||
fi
|
|
||||||
while IFS="=" read key value; do
|
|
||||||
case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
|
|
||||||
esac
|
|
||||||
done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
|
|
||||||
if [ "$MVNW_VERBOSE" = true ]; then
|
|
||||||
echo "Downloading from: $jarUrl"
|
|
||||||
fi
|
|
||||||
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
|
|
||||||
if $cygwin; then
|
|
||||||
wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
|
|
||||||
fi
|
|
||||||
|
|
||||||
if command -v wget > /dev/null; then
|
|
||||||
if [ "$MVNW_VERBOSE" = true ]; then
|
|
||||||
echo "Found wget ... using wget"
|
|
||||||
fi
|
|
||||||
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
|
||||||
wget "$jarUrl" -O "$wrapperJarPath"
|
|
||||||
else
|
|
||||||
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
|
|
||||||
fi
|
|
||||||
elif command -v curl > /dev/null; then
|
|
||||||
if [ "$MVNW_VERBOSE" = true ]; then
|
|
||||||
echo "Found curl ... using curl"
|
|
||||||
fi
|
|
||||||
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
|
||||||
curl -o "$wrapperJarPath" "$jarUrl" -f
|
|
||||||
else
|
|
||||||
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
|
|
||||||
fi
|
|
||||||
|
|
||||||
else
|
|
||||||
if [ "$MVNW_VERBOSE" = true ]; then
|
|
||||||
echo "Falling back to using Java to download"
|
|
||||||
fi
|
|
||||||
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
|
|
||||||
# For Cygwin, switch paths to Windows format before running javac
|
|
||||||
if $cygwin; then
|
|
||||||
javaClass=`cygpath --path --windows "$javaClass"`
|
|
||||||
fi
|
|
||||||
if [ -e "$javaClass" ]; then
|
|
||||||
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
|
|
||||||
if [ "$MVNW_VERBOSE" = true ]; then
|
|
||||||
echo " - Compiling MavenWrapperDownloader.java ..."
|
|
||||||
fi
|
|
||||||
# Compiling the Java class
|
|
||||||
("$JAVA_HOME/bin/javac" "$javaClass")
|
|
||||||
fi
|
|
||||||
if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
|
|
||||||
# Running the downloader
|
|
||||||
if [ "$MVNW_VERBOSE" = true ]; then
|
|
||||||
echo " - Running MavenWrapperDownloader.java ..."
|
|
||||||
fi
|
|
||||||
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
##########################################################################################
|
|
||||||
# End of extension
|
|
||||||
##########################################################################################
|
|
||||||
|
|
||||||
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
|
|
||||||
if [ "$MVNW_VERBOSE" = true ]; then
|
|
||||||
echo $MAVEN_PROJECTBASEDIR
|
|
||||||
fi
|
|
||||||
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
|
|
||||||
|
|
||||||
# For Cygwin, switch paths to Windows format before running java
|
|
||||||
if $cygwin; then
|
|
||||||
[ -n "$M2_HOME" ] &&
|
|
||||||
M2_HOME=`cygpath --path --windows "$M2_HOME"`
|
|
||||||
[ -n "$JAVA_HOME" ] &&
|
|
||||||
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
|
|
||||||
[ -n "$CLASSPATH" ] &&
|
|
||||||
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
|
|
||||||
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
|
|
||||||
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Provide a "standardized" way to retrieve the CLI args that will
|
|
||||||
# work with both Windows and non-Windows executions.
|
|
||||||
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
|
|
||||||
export MAVEN_CMD_LINE_ARGS
|
|
||||||
|
|
||||||
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
|
||||||
|
|
||||||
exec "$JAVACMD" \
|
|
||||||
$MAVEN_OPTS \
|
|
||||||
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
|
|
||||||
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
|
|
||||||
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
|
|
||||||
182
mvnw.cmd
vendored
182
mvnw.cmd
vendored
@@ -1,182 +0,0 @@
|
|||||||
@REM ----------------------------------------------------------------------------
|
|
||||||
@REM Licensed to the Apache Software Foundation (ASF) under one
|
|
||||||
@REM or more contributor license agreements. See the NOTICE file
|
|
||||||
@REM distributed with this work for additional information
|
|
||||||
@REM regarding copyright ownership. The ASF licenses this file
|
|
||||||
@REM to you under the Apache License, Version 2.0 (the
|
|
||||||
@REM "License"); you may not use this file except in compliance
|
|
||||||
@REM with the License. You may obtain a copy of the License at
|
|
||||||
@REM
|
|
||||||
@REM http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
@REM
|
|
||||||
@REM Unless required by applicable law or agreed to in writing,
|
|
||||||
@REM software distributed under the License is distributed on an
|
|
||||||
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
@REM KIND, either express or implied. See the License for the
|
|
||||||
@REM specific language governing permissions and limitations
|
|
||||||
@REM under the License.
|
|
||||||
@REM ----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
@REM ----------------------------------------------------------------------------
|
|
||||||
@REM Maven Start Up Batch script
|
|
||||||
@REM
|
|
||||||
@REM Required ENV vars:
|
|
||||||
@REM JAVA_HOME - location of a JDK home dir
|
|
||||||
@REM
|
|
||||||
@REM Optional ENV vars
|
|
||||||
@REM M2_HOME - location of maven2's installed home dir
|
|
||||||
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
|
|
||||||
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
|
|
||||||
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
|
||||||
@REM e.g. to debug Maven itself, use
|
|
||||||
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
|
||||||
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
|
||||||
@REM ----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
|
|
||||||
@echo off
|
|
||||||
@REM set title of command window
|
|
||||||
title %0
|
|
||||||
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
|
|
||||||
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
|
|
||||||
|
|
||||||
@REM set %HOME% to equivalent of $HOME
|
|
||||||
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
|
|
||||||
|
|
||||||
@REM Execute a user defined script before this one
|
|
||||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
|
|
||||||
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
|
|
||||||
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
|
|
||||||
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
|
|
||||||
:skipRcPre
|
|
||||||
|
|
||||||
@setlocal
|
|
||||||
|
|
||||||
set ERROR_CODE=0
|
|
||||||
|
|
||||||
@REM To isolate internal variables from possible post scripts, we use another setlocal
|
|
||||||
@setlocal
|
|
||||||
|
|
||||||
@REM ==== START VALIDATION ====
|
|
||||||
if not "%JAVA_HOME%" == "" goto OkJHome
|
|
||||||
|
|
||||||
echo.
|
|
||||||
echo Error: JAVA_HOME not found in your environment. >&2
|
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
|
||||||
echo location of your Java installation. >&2
|
|
||||||
echo.
|
|
||||||
goto error
|
|
||||||
|
|
||||||
:OkJHome
|
|
||||||
if exist "%JAVA_HOME%\bin\java.exe" goto init
|
|
||||||
|
|
||||||
echo.
|
|
||||||
echo Error: JAVA_HOME is set to an invalid directory. >&2
|
|
||||||
echo JAVA_HOME = "%JAVA_HOME%" >&2
|
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
|
||||||
echo location of your Java installation. >&2
|
|
||||||
echo.
|
|
||||||
goto error
|
|
||||||
|
|
||||||
@REM ==== END VALIDATION ====
|
|
||||||
|
|
||||||
:init
|
|
||||||
|
|
||||||
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
|
|
||||||
@REM Fallback to current working directory if not found.
|
|
||||||
|
|
||||||
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
|
|
||||||
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
|
|
||||||
|
|
||||||
set EXEC_DIR=%CD%
|
|
||||||
set WDIR=%EXEC_DIR%
|
|
||||||
:findBaseDir
|
|
||||||
IF EXIST "%WDIR%"\.mvn goto baseDirFound
|
|
||||||
cd ..
|
|
||||||
IF "%WDIR%"=="%CD%" goto baseDirNotFound
|
|
||||||
set WDIR=%CD%
|
|
||||||
goto findBaseDir
|
|
||||||
|
|
||||||
:baseDirFound
|
|
||||||
set MAVEN_PROJECTBASEDIR=%WDIR%
|
|
||||||
cd "%EXEC_DIR%"
|
|
||||||
goto endDetectBaseDir
|
|
||||||
|
|
||||||
:baseDirNotFound
|
|
||||||
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
|
|
||||||
cd "%EXEC_DIR%"
|
|
||||||
|
|
||||||
:endDetectBaseDir
|
|
||||||
|
|
||||||
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
|
|
||||||
|
|
||||||
@setlocal EnableExtensions EnableDelayedExpansion
|
|
||||||
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
|
|
||||||
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
|
|
||||||
|
|
||||||
:endReadAdditionalConfig
|
|
||||||
|
|
||||||
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
|
|
||||||
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
|
|
||||||
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
|
||||||
|
|
||||||
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
|
|
||||||
|
|
||||||
FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
|
|
||||||
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
|
|
||||||
)
|
|
||||||
|
|
||||||
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
|
|
||||||
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
|
|
||||||
if exist %WRAPPER_JAR% (
|
|
||||||
if "%MVNW_VERBOSE%" == "true" (
|
|
||||||
echo Found %WRAPPER_JAR%
|
|
||||||
)
|
|
||||||
) else (
|
|
||||||
if not "%MVNW_REPOURL%" == "" (
|
|
||||||
SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
|
|
||||||
)
|
|
||||||
if "%MVNW_VERBOSE%" == "true" (
|
|
||||||
echo Couldn't find %WRAPPER_JAR%, downloading it ...
|
|
||||||
echo Downloading from: %DOWNLOAD_URL%
|
|
||||||
)
|
|
||||||
|
|
||||||
powershell -Command "&{"^
|
|
||||||
"$webclient = new-object System.Net.WebClient;"^
|
|
||||||
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
|
|
||||||
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
|
|
||||||
"}"^
|
|
||||||
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
|
|
||||||
"}"
|
|
||||||
if "%MVNW_VERBOSE%" == "true" (
|
|
||||||
echo Finished downloading %WRAPPER_JAR%
|
|
||||||
)
|
|
||||||
)
|
|
||||||
@REM End of extension
|
|
||||||
|
|
||||||
@REM Provide a "standardized" way to retrieve the CLI args that will
|
|
||||||
@REM work with both Windows and non-Windows executions.
|
|
||||||
set MAVEN_CMD_LINE_ARGS=%*
|
|
||||||
|
|
||||||
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
|
|
||||||
if ERRORLEVEL 1 goto error
|
|
||||||
goto end
|
|
||||||
|
|
||||||
:error
|
|
||||||
set ERROR_CODE=1
|
|
||||||
|
|
||||||
:end
|
|
||||||
@endlocal & set ERROR_CODE=%ERROR_CODE%
|
|
||||||
|
|
||||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
|
|
||||||
@REM check for post script, once with legacy .bat ending and once with .cmd ending
|
|
||||||
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
|
|
||||||
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
|
|
||||||
:skipRcPost
|
|
||||||
|
|
||||||
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
|
|
||||||
if "%MAVEN_BATCH_PAUSE%" == "on" pause
|
|
||||||
|
|
||||||
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
|
|
||||||
|
|
||||||
exit /B %ERROR_CODE%
|
|
||||||
102
pom.xml
102
pom.xml
@@ -6,114 +6,45 @@
|
|||||||
|
|
||||||
<groupId>com.imaginarycode.minecraft</groupId>
|
<groupId>com.imaginarycode.minecraft</groupId>
|
||||||
<artifactId>RedisBungee</artifactId>
|
<artifactId>RedisBungee</artifactId>
|
||||||
<version>0.6.5</version>
|
<packaging>pom</packaging>
|
||||||
|
<version>0.7.2-SNAPSHOT</version>
|
||||||
|
|
||||||
<repositories>
|
|
||||||
<repository>
|
|
||||||
<id>bungeecord-repo</id>
|
|
||||||
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
|
||||||
</repository>
|
|
||||||
</repositories>
|
|
||||||
|
|
||||||
<inceptionYear>2013</inceptionYear>
|
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<resources>
|
|
||||||
<resource>
|
|
||||||
<directory>src/main/resources</directory>
|
|
||||||
<filtering>true</filtering>
|
|
||||||
</resource>
|
|
||||||
</resources>
|
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
<version>3.8.1</version>
|
|
||||||
<configuration>
|
|
||||||
<source>1.8</source>
|
|
||||||
<target>1.8</target>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-shade-plugin</artifactId>
|
|
||||||
<version>3.2.4</version>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<phase>package</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>shade</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<relocations>
|
|
||||||
<relocation>
|
|
||||||
<pattern>redis.clients.jedis</pattern>
|
|
||||||
<shadedPattern>com.imaginarycode.minecraft.redisbungee.internal.jedis
|
|
||||||
</shadedPattern>
|
|
||||||
</relocation>
|
|
||||||
<relocation>
|
|
||||||
<pattern>redis.clients.util</pattern>
|
|
||||||
<shadedPattern>com.imaginarycode.minecraft.redisbungee.internal.jedisutil
|
|
||||||
</shadedPattern>
|
|
||||||
</relocation>
|
|
||||||
<relocation>
|
|
||||||
<pattern>org.apache.commons.pool</pattern>
|
|
||||||
<shadedPattern>com.imaginarycode.minecraft.redisbungee.internal.commonspool
|
|
||||||
</shadedPattern>
|
|
||||||
</relocation>
|
|
||||||
<relocation>
|
|
||||||
<pattern>com.squareup.okhttp</pattern>
|
|
||||||
<shadedPattern>com.imaginarycode.minecraft.redisbungee.internal.okhttp
|
|
||||||
</shadedPattern>
|
|
||||||
</relocation>
|
|
||||||
<relocation>
|
|
||||||
<pattern>okio</pattern>
|
|
||||||
<shadedPattern>com.imaginarycode.minecraft.redisbungee.internal.okio
|
|
||||||
</shadedPattern>
|
|
||||||
</relocation>
|
|
||||||
</relocations>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-javadoc-plugin</artifactId>
|
|
||||||
<version>3.3.0</version>
|
|
||||||
<configuration>
|
<configuration>
|
||||||
<source>8</source>
|
<source>8</source>
|
||||||
|
<target>8</target>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
<modules>
|
||||||
|
<module>RedisBungee-API</module>
|
||||||
|
<module>RedisBungee-Bungee</module>
|
||||||
|
<module>RedisBungee-BungeeEvents</module>
|
||||||
|
</modules>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.guava</groupId>
|
||||||
|
<artifactId>guava</artifactId>
|
||||||
|
<version>31.1-jre</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>redis.clients</groupId>
|
<groupId>redis.clients</groupId>
|
||||||
<artifactId>jedis</artifactId>
|
<artifactId>jedis</artifactId>
|
||||||
<version>3.6.3</version>
|
<version>4.2.3</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.commons</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
<artifactId>commons-pool2</artifactId>
|
<artifactId>commons-pool2</artifactId>
|
||||||
<version>2.10.0</version>
|
<version>2.11.1</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>net.md-5</groupId>
|
|
||||||
<artifactId>bungeecord-api</artifactId>
|
|
||||||
<version>1.17-R0.1-SNAPSHOT</version>
|
|
||||||
<type>jar</type>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.projectlombok</groupId>
|
|
||||||
<artifactId>lombok</artifactId>
|
|
||||||
<version>1.18.20</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.squareup.okhttp</groupId>
|
<groupId>com.squareup.okhttp</groupId>
|
||||||
<artifactId>okhttp</artifactId>
|
<artifactId>okhttp</artifactId>
|
||||||
@@ -127,4 +58,5 @@
|
|||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -1,77 +0,0 @@
|
|||||||
package com.imaginarycode.minecraft.redisbungee;
|
|
||||||
|
|
||||||
import lombok.AccessLevel;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
import net.md_5.bungee.api.CommandSender;
|
|
||||||
import net.md_5.bungee.api.chat.BaseComponent;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class is the CommandSender that RedisBungee uses to dispatch commands to BungeeCord.
|
|
||||||
* <p>
|
|
||||||
* It inherits all permissions of the console command sender. Sending messages and modifying permissions are no-ops.
|
|
||||||
*
|
|
||||||
* @author tuxed
|
|
||||||
* @since 0.2.3
|
|
||||||
*/
|
|
||||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
|
||||||
public class RedisBungeeCommandSender implements CommandSender {
|
|
||||||
static final RedisBungeeCommandSender instance = new RedisBungeeCommandSender();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return "RedisBungee";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sendMessage(String s) {
|
|
||||||
// no-op
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sendMessages(String... strings) {
|
|
||||||
// no-op
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sendMessage(BaseComponent... baseComponents) {
|
|
||||||
// no-op
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sendMessage(BaseComponent baseComponent) {
|
|
||||||
// no-op
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<String> getGroups() {
|
|
||||||
return Collections.emptySet();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addGroups(String... strings) {
|
|
||||||
// no-op
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removeGroups(String... strings) {
|
|
||||||
// no-op
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasPermission(String s) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setPermission(String s, boolean b) {
|
|
||||||
// no-op
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<String> getPermissions() {
|
|
||||||
return Collections.emptySet();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,356 +0,0 @@
|
|||||||
package com.imaginarycode.minecraft.redisbungee;
|
|
||||||
|
|
||||||
import com.google.common.base.Joiner;
|
|
||||||
import com.google.common.collect.HashMultimap;
|
|
||||||
import com.google.common.collect.Multimap;
|
|
||||||
import net.md_5.bungee.api.ChatColor;
|
|
||||||
import net.md_5.bungee.api.CommandSender;
|
|
||||||
import net.md_5.bungee.api.chat.BaseComponent;
|
|
||||||
import net.md_5.bungee.api.chat.ComponentBuilder;
|
|
||||||
import net.md_5.bungee.api.chat.TextComponent;
|
|
||||||
import net.md_5.bungee.api.config.ServerInfo;
|
|
||||||
import net.md_5.bungee.api.plugin.Command;
|
|
||||||
|
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.TreeSet;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class contains subclasses that are used for the commands RedisBungee overrides or includes: /glist, /find and /lastseen.
|
|
||||||
* <p>
|
|
||||||
* All classes use the {@link RedisBungeeAPI}.
|
|
||||||
*
|
|
||||||
* @author tuxed
|
|
||||||
* @since 0.2.3
|
|
||||||
*/
|
|
||||||
class RedisBungeeCommands {
|
|
||||||
private static final BaseComponent[] NO_PLAYER_SPECIFIED =
|
|
||||||
new ComponentBuilder("You must specify a player name.").color(ChatColor.RED).create();
|
|
||||||
private static final BaseComponent[] PLAYER_NOT_FOUND =
|
|
||||||
new ComponentBuilder("No such player found.").color(ChatColor.RED).create();
|
|
||||||
private static final BaseComponent[] NO_COMMAND_SPECIFIED =
|
|
||||||
new ComponentBuilder("You must specify a command to be run.").color(ChatColor.RED).create();
|
|
||||||
|
|
||||||
private static String playerPlural(int num) {
|
|
||||||
return num == 1 ? num + " player is" : num + " players are";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class GlistCommand extends Command {
|
|
||||||
private final RedisBungee plugin;
|
|
||||||
|
|
||||||
GlistCommand(RedisBungee plugin) {
|
|
||||||
super("glist", "bungeecord.command.list", "redisbungee", "rglist");
|
|
||||||
this.plugin = plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(final CommandSender sender, final String[] args) {
|
|
||||||
plugin.getProxy().getScheduler().runAsync(plugin, new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
int count = RedisBungee.getApi().getPlayerCount();
|
|
||||||
BaseComponent[] playersOnline = new ComponentBuilder("").color(ChatColor.YELLOW)
|
|
||||||
.append(playerPlural(count) + " currently online.").create();
|
|
||||||
if (args.length > 0 && args[0].equals("showall")) {
|
|
||||||
Multimap<String, UUID> serverToPlayers = RedisBungee.getApi().getServerToPlayers();
|
|
||||||
Multimap<String, String> human = HashMultimap.create();
|
|
||||||
for (Map.Entry<String, UUID> entry : serverToPlayers.entries()) {
|
|
||||||
human.put(entry.getKey(), plugin.getUuidTranslator().getNameFromUuid(entry.getValue(), false));
|
|
||||||
}
|
|
||||||
for (String server : new TreeSet<>(serverToPlayers.keySet())) {
|
|
||||||
TextComponent serverName = new TextComponent();
|
|
||||||
serverName.setColor(ChatColor.GREEN);
|
|
||||||
serverName.setText("[" + server + "] ");
|
|
||||||
TextComponent serverCount = new TextComponent();
|
|
||||||
serverCount.setColor(ChatColor.YELLOW);
|
|
||||||
serverCount.setText("(" + serverToPlayers.get(server).size() + "): ");
|
|
||||||
TextComponent serverPlayers = new TextComponent();
|
|
||||||
serverPlayers.setColor(ChatColor.WHITE);
|
|
||||||
serverPlayers.setText(Joiner.on(", ").join(human.get(server)));
|
|
||||||
sender.sendMessage(serverName, serverCount, serverPlayers);
|
|
||||||
}
|
|
||||||
sender.sendMessage(playersOnline);
|
|
||||||
} else {
|
|
||||||
sender.sendMessage(playersOnline);
|
|
||||||
sender.sendMessage(new ComponentBuilder("To see all players online, use /glist showall.").color(ChatColor.YELLOW).create());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class FindCommand extends Command {
|
|
||||||
private final RedisBungee plugin;
|
|
||||||
|
|
||||||
FindCommand(RedisBungee plugin) {
|
|
||||||
super("find", "bungeecord.command.find", "rfind");
|
|
||||||
this.plugin = plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(final CommandSender sender, final String[] args) {
|
|
||||||
plugin.getProxy().getScheduler().runAsync(plugin, new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (args.length > 0) {
|
|
||||||
UUID uuid = plugin.getUuidTranslator().getTranslatedUuid(args[0], true);
|
|
||||||
if (uuid == null) {
|
|
||||||
sender.sendMessage(PLAYER_NOT_FOUND);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ServerInfo si = RedisBungee.getApi().getServerFor(uuid);
|
|
||||||
if (si != null) {
|
|
||||||
TextComponent message = new TextComponent();
|
|
||||||
message.setColor(ChatColor.BLUE);
|
|
||||||
message.setText(args[0] + " is on " + si.getName() + ".");
|
|
||||||
sender.sendMessage(message);
|
|
||||||
} else {
|
|
||||||
sender.sendMessage(PLAYER_NOT_FOUND);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
sender.sendMessage(NO_PLAYER_SPECIFIED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class LastSeenCommand extends Command {
|
|
||||||
private final RedisBungee plugin;
|
|
||||||
|
|
||||||
LastSeenCommand(RedisBungee plugin) {
|
|
||||||
super("lastseen", "redisbungee.command.lastseen", "rlastseen");
|
|
||||||
this.plugin = plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(final CommandSender sender, final String[] args) {
|
|
||||||
plugin.getProxy().getScheduler().runAsync(plugin, new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (args.length > 0) {
|
|
||||||
UUID uuid = plugin.getUuidTranslator().getTranslatedUuid(args[0], true);
|
|
||||||
if (uuid == null) {
|
|
||||||
sender.sendMessage(PLAYER_NOT_FOUND);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
long secs = RedisBungee.getApi().getLastOnline(uuid);
|
|
||||||
TextComponent message = new TextComponent();
|
|
||||||
if (secs == 0) {
|
|
||||||
message.setColor(ChatColor.GREEN);
|
|
||||||
message.setText(args[0] + " is currently online.");
|
|
||||||
} else if (secs != -1) {
|
|
||||||
message.setColor(ChatColor.BLUE);
|
|
||||||
message.setText(args[0] + " was last online on " + new SimpleDateFormat().format(secs) + ".");
|
|
||||||
} else {
|
|
||||||
message.setColor(ChatColor.RED);
|
|
||||||
message.setText(args[0] + " has never been online.");
|
|
||||||
}
|
|
||||||
sender.sendMessage(message);
|
|
||||||
} else {
|
|
||||||
sender.sendMessage(NO_PLAYER_SPECIFIED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class IpCommand extends Command {
|
|
||||||
private final RedisBungee plugin;
|
|
||||||
|
|
||||||
IpCommand(RedisBungee plugin) {
|
|
||||||
super("ip", "redisbungee.command.ip", "playerip", "rip", "rplayerip");
|
|
||||||
this.plugin = plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(final CommandSender sender, final String[] args) {
|
|
||||||
plugin.getProxy().getScheduler().runAsync(plugin, new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (args.length > 0) {
|
|
||||||
UUID uuid = plugin.getUuidTranslator().getTranslatedUuid(args[0], true);
|
|
||||||
if (uuid == null) {
|
|
||||||
sender.sendMessage(PLAYER_NOT_FOUND);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
InetAddress ia = RedisBungee.getApi().getPlayerIp(uuid);
|
|
||||||
if (ia != null) {
|
|
||||||
TextComponent message = new TextComponent();
|
|
||||||
message.setColor(ChatColor.GREEN);
|
|
||||||
message.setText(args[0] + " is connected from " + ia.toString() + ".");
|
|
||||||
sender.sendMessage(message);
|
|
||||||
} else {
|
|
||||||
sender.sendMessage(PLAYER_NOT_FOUND);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
sender.sendMessage(NO_PLAYER_SPECIFIED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class PlayerProxyCommand extends Command {
|
|
||||||
private final RedisBungee plugin;
|
|
||||||
|
|
||||||
PlayerProxyCommand(RedisBungee plugin) {
|
|
||||||
super("pproxy", "redisbungee.command.pproxy");
|
|
||||||
this.plugin = plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(final CommandSender sender, final String[] args) {
|
|
||||||
plugin.getProxy().getScheduler().runAsync(plugin, new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (args.length > 0) {
|
|
||||||
UUID uuid = plugin.getUuidTranslator().getTranslatedUuid(args[0], true);
|
|
||||||
if (uuid == null) {
|
|
||||||
sender.sendMessage(PLAYER_NOT_FOUND);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String proxy = RedisBungee.getApi().getProxy(uuid);
|
|
||||||
if (proxy != null) {
|
|
||||||
TextComponent message = new TextComponent();
|
|
||||||
message.setColor(ChatColor.GREEN);
|
|
||||||
message.setText(args[0] + " is connected to " + proxy + ".");
|
|
||||||
sender.sendMessage(message);
|
|
||||||
} else {
|
|
||||||
sender.sendMessage(PLAYER_NOT_FOUND);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
sender.sendMessage(NO_PLAYER_SPECIFIED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class SendToAll extends Command {
|
|
||||||
private final RedisBungee plugin;
|
|
||||||
|
|
||||||
SendToAll(RedisBungee plugin) {
|
|
||||||
super("sendtoall", "redisbungee.command.sendtoall", "rsendtoall");
|
|
||||||
this.plugin = plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(CommandSender sender, String[] args) {
|
|
||||||
if (args.length > 0) {
|
|
||||||
String command = Joiner.on(" ").skipNulls().join(args);
|
|
||||||
RedisBungee.getApi().sendProxyCommand(command);
|
|
||||||
TextComponent message = new TextComponent();
|
|
||||||
message.setColor(ChatColor.GREEN);
|
|
||||||
message.setText("Sent the command /" + command + " to all proxies.");
|
|
||||||
sender.sendMessage(message);
|
|
||||||
} else {
|
|
||||||
sender.sendMessage(NO_COMMAND_SPECIFIED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ServerId extends Command {
|
|
||||||
private final RedisBungee plugin;
|
|
||||||
|
|
||||||
ServerId(RedisBungee plugin) {
|
|
||||||
super("serverid", "redisbungee.command.serverid", "rserverid");
|
|
||||||
this.plugin = plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(CommandSender sender, String[] args) {
|
|
||||||
TextComponent textComponent = new TextComponent();
|
|
||||||
textComponent.setText("You are on " + RedisBungee.getApi().getServerId() + ".");
|
|
||||||
textComponent.setColor(ChatColor.YELLOW);
|
|
||||||
sender.sendMessage(textComponent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ServerIds extends Command {
|
|
||||||
public ServerIds() {
|
|
||||||
super("serverids", "redisbungee.command.serverids");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(CommandSender sender, String[] strings) {
|
|
||||||
TextComponent textComponent = new TextComponent();
|
|
||||||
textComponent.setText("All server IDs: " + Joiner.on(", ").join(RedisBungee.getApi().getAllServers()));
|
|
||||||
textComponent.setColor(ChatColor.YELLOW);
|
|
||||||
sender.sendMessage(textComponent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class PlistCommand extends Command {
|
|
||||||
private final RedisBungee plugin;
|
|
||||||
|
|
||||||
PlistCommand(RedisBungee plugin) {
|
|
||||||
super("plist", "redisbungee.command.plist", "rplist");
|
|
||||||
this.plugin = plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(final CommandSender sender, final String[] args) {
|
|
||||||
plugin.getProxy().getScheduler().runAsync(plugin, new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
String proxy = args.length >= 1 ? args[0] : RedisBungee.getConfiguration().getServerId();
|
|
||||||
if (!plugin.getServerIds().contains(proxy)) {
|
|
||||||
sender.sendMessage(new ComponentBuilder(proxy + " is not a valid proxy. See /serverids for valid proxies.").color(ChatColor.RED).create());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Set<UUID> players = RedisBungee.getApi().getPlayersOnProxy(proxy);
|
|
||||||
BaseComponent[] playersOnline = new ComponentBuilder("").color(ChatColor.YELLOW)
|
|
||||||
.append(playerPlural(players.size()) + " currently on proxy " + proxy + ".").create();
|
|
||||||
if (args.length >= 2 && args[1].equals("showall")) {
|
|
||||||
Multimap<String, UUID> serverToPlayers = RedisBungee.getApi().getServerToPlayers();
|
|
||||||
Multimap<String, String> human = HashMultimap.create();
|
|
||||||
for (Map.Entry<String, UUID> entry : serverToPlayers.entries()) {
|
|
||||||
if (players.contains(entry.getValue())) {
|
|
||||||
human.put(entry.getKey(), plugin.getUuidTranslator().getNameFromUuid(entry.getValue(), false));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (String server : new TreeSet<>(human.keySet())) {
|
|
||||||
TextComponent serverName = new TextComponent();
|
|
||||||
serverName.setColor(ChatColor.RED);
|
|
||||||
serverName.setText("[" + server + "] ");
|
|
||||||
TextComponent serverCount = new TextComponent();
|
|
||||||
serverCount.setColor(ChatColor.YELLOW);
|
|
||||||
serverCount.setText("(" + human.get(server).size() + "): ");
|
|
||||||
TextComponent serverPlayers = new TextComponent();
|
|
||||||
serverPlayers.setColor(ChatColor.WHITE);
|
|
||||||
serverPlayers.setText(Joiner.on(", ").join(human.get(server)));
|
|
||||||
sender.sendMessage(serverName, serverCount, serverPlayers);
|
|
||||||
}
|
|
||||||
sender.sendMessage(playersOnline);
|
|
||||||
} else {
|
|
||||||
sender.sendMessage(playersOnline);
|
|
||||||
sender.sendMessage(new ComponentBuilder("To see all players online, use /plist " + proxy + " showall.").color(ChatColor.YELLOW).create());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class DebugCommand extends Command {
|
|
||||||
private final RedisBungee plugin;
|
|
||||||
|
|
||||||
DebugCommand(RedisBungee plugin) {
|
|
||||||
super("rdebug", "redisbungee.command.debug");
|
|
||||||
this.plugin = plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(final CommandSender sender, final String[] args) {
|
|
||||||
TextComponent poolActiveStat = new TextComponent("Currently active pool objects: " + plugin.getPool().getNumActive());
|
|
||||||
TextComponent poolIdleStat = new TextComponent("Currently idle pool objects: " + plugin.getPool().getNumIdle());
|
|
||||||
TextComponent poolWaitingStat = new TextComponent("Waiting on free objects: " + plugin.getPool().getNumWaiters());
|
|
||||||
sender.sendMessage(poolActiveStat);
|
|
||||||
sender.sendMessage(poolIdleStat);
|
|
||||||
sender.sendMessage(poolWaitingStat);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
package com.imaginarycode.minecraft.redisbungee;
|
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
|
||||||
import com.google.common.net.InetAddresses;
|
|
||||||
import lombok.Getter;
|
|
||||||
import net.md_5.bungee.config.Configuration;
|
|
||||||
import redis.clients.jedis.JedisPool;
|
|
||||||
|
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public class RedisBungeeConfiguration {
|
|
||||||
@Getter
|
|
||||||
private final JedisPool pool;
|
|
||||||
@Getter
|
|
||||||
private final String serverId;
|
|
||||||
@Getter
|
|
||||||
private final boolean registerBungeeCommands;
|
|
||||||
@Getter
|
|
||||||
private final List<InetAddress> exemptAddresses;
|
|
||||||
|
|
||||||
|
|
||||||
public RedisBungeeConfiguration(JedisPool pool, Configuration configuration, String randomUUID) {
|
|
||||||
this.pool = pool;
|
|
||||||
if (configuration.getBoolean("use-random-id-string", false)) {
|
|
||||||
this.serverId = configuration.getString("server-id") + "-" + randomUUID;
|
|
||||||
} else {
|
|
||||||
this.serverId = configuration.getString("server-id");
|
|
||||||
}
|
|
||||||
|
|
||||||
this.registerBungeeCommands = configuration.getBoolean("register-bungee-commands", true);
|
|
||||||
|
|
||||||
List<String> stringified = configuration.getStringList("exempt-ip-addresses");
|
|
||||||
ImmutableList.Builder<InetAddress> addressBuilder = ImmutableList.builder();
|
|
||||||
|
|
||||||
for (String s : stringified) {
|
|
||||||
addressBuilder.add(InetAddresses.forString(s));
|
|
||||||
}
|
|
||||||
|
|
||||||
this.exemptAddresses = addressBuilder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
package com.imaginarycode.minecraft.redisbungee;
|
|
||||||
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
|
||||||
import lombok.AccessLevel;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
import net.md_5.bungee.api.connection.PendingConnection;
|
|
||||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
|
||||||
import redis.clients.jedis.Jedis;
|
|
||||||
import redis.clients.jedis.Pipeline;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
|
||||||
public class RedisUtil {
|
|
||||||
protected static void createPlayer(ProxiedPlayer player, Pipeline pipeline, boolean fireEvent) {
|
|
||||||
createPlayer(player.getPendingConnection(), pipeline, fireEvent);
|
|
||||||
if (player.getServer() != null)
|
|
||||||
pipeline.hset("player:" + player.getUniqueId().toString(), "server", player.getServer().getInfo().getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static void createPlayer(PendingConnection connection, Pipeline pipeline, boolean fireEvent) {
|
|
||||||
Map<String, String> playerData = new HashMap<>(4);
|
|
||||||
playerData.put("online", "0");
|
|
||||||
playerData.put("ip", connection.getAddress().getAddress().getHostAddress());
|
|
||||||
playerData.put("proxy", RedisBungee.getConfiguration().getServerId());
|
|
||||||
|
|
||||||
pipeline.sadd("proxy:" + RedisBungee.getApi().getServerId() + ":usersOnline", connection.getUniqueId().toString());
|
|
||||||
pipeline.hmset("player:" + connection.getUniqueId().toString(), playerData);
|
|
||||||
|
|
||||||
if (fireEvent) {
|
|
||||||
pipeline.publish("redisbungee-data", RedisBungee.getGson().toJson(new DataManager.DataManagerMessage<>(
|
|
||||||
connection.getUniqueId(), DataManager.DataManagerMessage.Action.JOIN,
|
|
||||||
new DataManager.LoginPayload(connection.getAddress().getAddress()))));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void cleanUpPlayer(String player, Jedis rsc) {
|
|
||||||
rsc.srem("proxy:" + RedisBungee.getApi().getServerId() + ":usersOnline", player);
|
|
||||||
rsc.hdel("player:" + player, "server", "ip", "proxy");
|
|
||||||
long timestamp = System.currentTimeMillis();
|
|
||||||
rsc.hset("player:" + player, "online", String.valueOf(timestamp));
|
|
||||||
rsc.publish("redisbungee-data", RedisBungee.getGson().toJson(new DataManager.DataManagerMessage<>(
|
|
||||||
UUID.fromString(player), DataManager.DataManagerMessage.Action.LEAVE,
|
|
||||||
new DataManager.LogoutPayload(timestamp))));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void cleanUpPlayer(String player, Pipeline rsc) {
|
|
||||||
rsc.srem("proxy:" + RedisBungee.getApi().getServerId() + ":usersOnline", player);
|
|
||||||
rsc.hdel("player:" + player, "server", "ip", "proxy");
|
|
||||||
long timestamp = System.currentTimeMillis();
|
|
||||||
rsc.hset("player:" + player, "online", String.valueOf(timestamp));
|
|
||||||
rsc.publish("redisbungee-data", RedisBungee.getGson().toJson(new DataManager.DataManagerMessage<>(
|
|
||||||
UUID.fromString(player), DataManager.DataManagerMessage.Action.LEAVE,
|
|
||||||
new DataManager.LogoutPayload(timestamp))));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean canUseLua(String redisVersion) {
|
|
||||||
// Need to use >=6.2 to use Lua optimizations.
|
|
||||||
String[] args = redisVersion.split("\\.");
|
|
||||||
if (args.length < 2) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
int major = Integer.parseInt(args[0]);
|
|
||||||
int minor = Integer.parseInt(args[1]);
|
|
||||||
return major >= 6 && minor >= 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
package com.imaginarycode.minecraft.redisbungee.test;
|
|
||||||
|
|
||||||
import com.imaginarycode.minecraft.redisbungee.RedisUtil;
|
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
public class RedisUtilTest {
|
|
||||||
@Test
|
|
||||||
public void testRedisLuaCheck() {
|
|
||||||
Assert.assertTrue(RedisUtil.canUseLua("6.2.0"));
|
|
||||||
Assert.assertTrue(RedisUtil.canUseLua("6.1.0"));
|
|
||||||
Assert.assertTrue(RedisUtil.canUseLua("6.0.0"));
|
|
||||||
Assert.assertFalse(RedisUtil.canUseLua("2.6.0"));
|
|
||||||
Assert.assertFalse(RedisUtil.canUseLua("2.2.12"));
|
|
||||||
Assert.assertFalse(RedisUtil.canUseLua("1.2.4"));
|
|
||||||
Assert.assertFalse(RedisUtil.canUseLua("2.8.4"));
|
|
||||||
Assert.assertFalse(RedisUtil.canUseLua("3.0.0"));
|
|
||||||
Assert.assertFalse(RedisUtil.canUseLua("3.2.1"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
package com.imaginarycode.minecraft.redisbungee.test;
|
|
||||||
|
|
||||||
import com.imaginarycode.minecraft.redisbungee.util.uuid.NameFetcher;
|
|
||||||
import com.imaginarycode.minecraft.redisbungee.util.uuid.UUIDFetcher;
|
|
||||||
import com.squareup.okhttp.OkHttpClient;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public class UUIDNameTest {
|
|
||||||
private String[] uuidsToTest = {"68ec43f7234b41b48764dfb38b9ffe8c", "652a2bc4e8cd405db7b698156ee2dc09"};
|
|
||||||
private String[] namesToTest = {"vemacs"};
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testUuidToName() throws IOException {
|
|
||||||
OkHttpClient httpClient = new OkHttpClient();
|
|
||||||
NameFetcher.setHttpClient(httpClient);
|
|
||||||
for (String uuid : uuidsToTest) {
|
|
||||||
List<String> names = NameFetcher.nameHistoryFromUuid(UUIDFetcher.getUUID(uuid));
|
|
||||||
String currentName = names.get(names.size() - 1);
|
|
||||||
System.out.println("Current name for UUID " + uuid + " is " + currentName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testNameToUuid() throws IOException {
|
|
||||||
OkHttpClient httpClient = new OkHttpClient();
|
|
||||||
UUIDFetcher.setHttpClient(httpClient);
|
|
||||||
for (String name : namesToTest) {
|
|
||||||
Map<String, UUID> uuidMap1;
|
|
||||||
try {
|
|
||||||
uuidMap1 = new UUIDFetcher(Collections.singletonList(name)).call();
|
|
||||||
for (Map.Entry<String, UUID> entry : uuidMap1.entrySet()) {
|
|
||||||
if (entry.getKey().equalsIgnoreCase(name)) {
|
|
||||||
System.out.println("Current UUID for name " + name + " is " + entry.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user