Compare commits

...

36 Commits

Author SHA1 Message Date
ME1312 d1cb53e0f5
Reoptimize the recycle cleaners 2023-12-24 19:07:54 -05:00
ME1312 903b8a98d3
Optimize the recycle cleaners #87 2023-12-24 18:46:25 -05:00
ME1312 f7f42c8ba9
VanillaCord 2.0 2023-12-22 19:23:48 -05:00
ME1312 ad24b0deb3
Trigger reconnect sequence for linking errors, too 2023-08-12 00:07:05 -04:00
ME1312 78f50e77b2
#83 Fixes some template inheritance issues 2023-05-25 22:22:09 -04:00
ME1312 c511ded3d4
Remove duplicate plugins folder
If you have encountered this issue, know that the correct plugins folder is named `Plugins`.
2023-05-21 22:43:43 -04:00
ME1312 b5cddeb892
Fixes deserialization of UUIDs 2023-05-06 06:00:30 -04:00
ME1312 7d9fabd2b9
Fixes your assembly xml 2023-04-09 09:01:06 -04:00
ME1312 b23aa18661
Ensure folia is not required to compile against us 2023-04-09 05:29:41 -04:00
ME1312 ba80e0a16a
Folia scheduling support
Plugins that depend on SubServers.Client can make use of our platform-`AgnosticScheduler` to achieve the same results
2023-04-09 04:25:30 -04:00
ME1312 ecf76a97de
Reduced and updated dependancies
Also includes potential fixes for external host state desyncing
2023-04-07 22:47:16 -04:00
ME1312 01456fd964
Updated SubData 2023-02-22 17:50:02 -05:00
ME1312 c90dbc8e3f
Updated GalaxiEngine 2023-02-22 17:28:52 -05:00
ME1312 e02093ab2f
Updated dependancies 2023-02-22 16:36:40 -05:00
ME1312 8a5a0cdc4b
Fixes to ping adjustment for global player count 2023-01-10 00:57:31 -05:00
ME1312 cf07e86a09
Mirror the listeners field 2022-12-18 14:30:32 -05:00
ME1312 d8463e25c5
Fix the state of CTRL+C shutdowns 2022-11-12 22:40:43 -05:00
ME1312 cb6d30c882
Fix javadoc linking 2022-10-26 15:12:22 -04:00
ME1312 c5377f7f13
Make the status button clickable 2022-10-26 15:02:06 -04:00
ME1312 36f2821524
#80 Bring creation event handling up to spec 2022-08-17 13:18:44 -04:00
ME1312 41dd2d69d0
Add `subservers:input` for 1.19+
This is a simple plugin message channel that simulates chat spoofing.
2022-06-15 11:54:36 -04:00
ME1312 307ac43df0
Fix PacketExControlPlayer 2022-05-28 05:59:33 -04:00
ME1312 1521acfc51
Fix brief shutdown hang in SubServers.Client 2022-04-12 07:59:33 -04:00
ME1312 ce262c62f0
Fix potential NPE 2022-04-09 21:03:29 -04:00
ME1312 e4300e76e2
Make our bukkit events async
Also, #76 store signs in instance
2022-04-05 19:26:50 -04:00
ME1312 7d9de9bf6e
I'm done now i swear 2022-03-19 14:48:16 -04:00
ME1312 249b0a4fab
Yet more minor tweaks to signs 2022-03-19 13:14:22 -04:00
ME1312 6fc8732003
Revert to instance checking for signs 2022-03-19 12:25:19 -04:00
ME1312 b7c89d26d5
Minor sign efficiency upgrades 2022-03-18 17:16:29 -04:00
ME1312 a4d9f46084
Fix possible NPE 2022-03-18 12:30:54 -04:00
ME1312 58ae08db1e
Improved efficiency when accessing maps
Also, #75 Support for hosts, groups, and external servers on signs
2022-03-18 11:57:38 -04:00
ME1312 f6ce5c92fb
Update lang.yml 2022-03-17 01:42:17 -04:00
ME1312 7433fc04a8
#75 Added Server Signs 2022-03-17 00:18:34 -04:00
ME1312 5454590874
Minor sequence correction 2022-02-15 11:43:25 -05:00
ME1312 3e78536d08
Fix rogue detection for remote subservers 2022-02-15 11:36:07 -05:00
ME1312 8a18b6f5d1
Some minor fixes 2022-02-14 12:53:55 -05:00
222 changed files with 3291 additions and 3010 deletions

View File

@ -11,7 +11,7 @@ Paste in the version information from the SubServers app in question here. To ge
Here you can write about what happened that shouldn't have. If you have any errors in your console related to what happened, you should also paste those here.
### How It Happened
Tell us step-by-step how to recreate the problem. This step is vital for us to determine whether or not the problem happens to everyone else too.
Tell us step-by-step how to recreate the problem. This step is vital for us to determine whether the problem happens to everyone else too.
### Additional Information
Here you can provide any extra details you may think useful for solving the problem.

View File

@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright (C) 2015-2021 ME1312
Copyright (C) 2015-2023 ME1312
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@ -27,8 +27,8 @@
</dependency>
<dependency>
<groupId>net.ME1312.Galaxi</groupId>
<artifactId>GalaxiUtil</artifactId>
<version>21w50a</version>
<artifactId>GalaxiBase</artifactId>
<version>23w51a</version>
<scope>compile</scope>
</dependency>
</dependencies>
@ -100,7 +100,7 @@
<reportOutputDirectory>${basedir}/../../Javadoc/SubServers.Bungee.Common</reportOutputDirectory>
<additionalOptions>-Xdoclint:none</additionalOptions>
<links>
<link>https://dev.me1312.net/jenkins/job/GalaxiEngine/javadoc/GalaxiUtil/</link>
<link>https://dev.me1312.net/jenkins/job/GalaxiEngine/javadoc/GalaxiBase/</link>
<link>https://ci.md-5.net/job/BungeeCord/ws/api/target/apidocs/</link>
</links>
</configuration>

View File

@ -1,9 +1,12 @@
package net.ME1312.SubServers.Bungee;
import net.ME1312.Galaxi.Library.Util;
import io.netty.channel.Channel;
import net.md_5.bungee.BungeeCord;
import net.md_5.bungee.api.config.ServerInfo;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import java.util.function.Supplier;
@ -13,8 +16,10 @@ import java.util.function.Supplier;
public abstract class BungeeCommon extends BungeeCord {
private static BungeeCommon instance;
final Supplier<BungeeAPI> api;
protected final Collection<Channel> listeners;
protected BungeeCommon(Supplier<BungeeAPI> api) throws IOException {
protected BungeeCommon(Supplier<BungeeAPI> api) throws Exception {
listeners= Util.reflect(BungeeCord.class.getDeclaredField("listeners"), this);
this.api = api;
instance = this;
}

View File

@ -19,7 +19,7 @@ public class Logger {
* @return Logger
*/
public static java.util.logging.Logger get(String prefix) {
if (!existing.keySet().contains(prefix)) {
if (!existing.containsKey(prefix)) {
java.util.logging.Logger log = java.util.logging.Logger.getAnonymousLogger();
log.setUseParentHandlers(false);
log.addHandler(new Handler() {

View File

@ -153,7 +153,7 @@ public class SmartFallback implements ReconnectHandler {
}
if (valid) {
List<ServerInfo> servers = (score.keySet().contains(confidence))?score.get(confidence):new LinkedList<ServerInfo>();
List<ServerInfo> servers = (score.containsKey(confidence))?score.get(confidence):new LinkedList<ServerInfo>();
servers.add(server);
score.put(confidence, servers);
}

View File

@ -1,6 +1,7 @@
package net.ME1312.SubServers.Sync.Library;
package net.ME1312.SubServers.Bungee.Library;
import net.ME1312.SubServers.Sync.SubAPI;
import net.ME1312.SubServers.Bungee.BungeeAPI;
import net.ME1312.SubServers.Bungee.BungeeCommon;
import gnu.trove.map.hash.TIntObjectHashMap;
import net.md_5.bungee.api.ProxyServer;
@ -29,6 +30,9 @@ import java.util.logging.Level;
import java.util.stream.Collectors;
import java.util.zip.GZIPOutputStream;
/**
* SubServers BStats Metrics Implementation
*/
public class Metrics {
private final Plugin plugin;
@ -79,7 +83,6 @@ public class Metrics {
logResponseStatusText);
}
/** Loads the bStats configuration. */
private void loadConfig() throws IOException {
File bStatsFolder = new File(plugin.getDataFolder().getParentFile(), "bStats");
@ -118,15 +121,6 @@ public class Metrics {
}
}
/**
* Adds a custom chart.
*
* @param chart The chart to add.
*/
public void addCustomChart(CustomChart chart) {
metricsBase.addCustomChart(chart);
}
private static final AdvancedPie PLAYER_VERSIONS;
static {
final int[] PROTOCOL_VERSIONS;
@ -169,20 +163,26 @@ public class Metrics {
});
}
public void appendAppData() {
addCustomChart(PLAYER_VERSIONS);
/**
* Add subservers platform information as custom charts
*/
public Metrics addPlatformCharts() {
return addCustomChart(new SimplePie("subservers_version", () -> BungeeAPI.getInstance().getWrapperVersion().toString())).addCustomChart(PLAYER_VERSIONS);
}
public void appendPluginData() {
addCustomChart(new SimplePie("subservers_version", () -> {
return SubAPI.getInstance().getWrapperVersion().toString();
}));
addCustomChart(PLAYER_VERSIONS);
/**
* Adds a custom chart.
*
* @param chart The chart to add.
*/
public Metrics addCustomChart(CustomChart chart) {
metricsBase.addCustomChart(chart);
return this;
}
private void appendPlatformData(JsonObjectBuilder builder) {
builder.appendField("playerAmount", plugin.getProxy().getOnlineCount());
builder.appendField("managedServers", plugin.getProxy().getServers().size());
builder.appendField("managedServers", ((BungeeCommon) plugin.getProxy()).getServersCopy().size());
builder.appendField("onlineMode", plugin.getProxy().getConfig().isOnlineMode() ? 1 : 0);
builder.appendField("bungeecordVersion", plugin.getProxy().getVersion());
builder.appendField("javaVersion", System.getProperty("java.version"));
@ -199,7 +199,7 @@ public class Metrics {
public static class MetricsBase {
/** The version of the Metrics class. */
public static final String METRICS_VERSION = "2.2.1";
public static final String METRICS_VERSION = "3.0.0";
private static final ScheduledExecutorService scheduler =
Executors.newScheduledThreadPool(1, task -> new Thread(task, "bStats-Metrics"));
@ -284,6 +284,7 @@ public class Metrics {
this.logResponseStatusText = logResponseStatusText;
checkRelocation();
if (enabled) {
// WARNING: Removing the option to opt-out will get your plugin banned from bStats
startSubmitting();
}
}
@ -420,9 +421,9 @@ public class Metrics {
}
}
public static class AdvancedBarChart extends CustomChart {
public static class DrilldownPie extends CustomChart {
private final Callable<Map<String, int[]>> callable;
private final Callable<Map<String, Map<String, Integer>>> callable;
/**
* Class constructor.
@ -430,99 +431,33 @@ public class Metrics {
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public AdvancedBarChart(String chartId, Callable<Map<String, int[]>> callable) {
public DrilldownPie(String chartId, Callable<Map<String, Map<String, Integer>>> callable) {
super(chartId);
this.callable = callable;
}
@Override
protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
public JsonObjectBuilder.JsonObject getChartData() throws Exception {
JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
Map<String, int[]> map = callable.call();
Map<String, Map<String, Integer>> map = callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
return null;
}
boolean allSkipped = true;
for (Map.Entry<String, int[]> entry : map.entrySet()) {
if (entry.getValue().length == 0) {
// Skip this invalid
continue;
boolean reallyAllSkipped = true;
for (Map.Entry<String, Map<String, Integer>> entryValues : map.entrySet()) {
JsonObjectBuilder valueBuilder = new JsonObjectBuilder();
boolean allSkipped = true;
for (Map.Entry<String, Integer> valueEntry : map.get(entryValues.getKey()).entrySet()) {
valueBuilder.appendField(valueEntry.getKey(), valueEntry.getValue());
allSkipped = false;
}
allSkipped = false;
valuesBuilder.appendField(entry.getKey(), entry.getValue());
}
if (allSkipped) {
// Null = skip the chart
return null;
}
return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build();
}
}
public static class SimpleBarChart extends CustomChart {
private final Callable<Map<String, Integer>> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public SimpleBarChart(String chartId, Callable<Map<String, Integer>> callable) {
super(chartId);
this.callable = callable;
}
@Override
protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
Map<String, Integer> map = callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
return null;
}
for (Map.Entry<String, Integer> entry : map.entrySet()) {
valuesBuilder.appendField(entry.getKey(), new int[] {entry.getValue()});
}
return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build();
}
}
public static class MultiLineChart extends CustomChart {
private final Callable<Map<String, Integer>> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public MultiLineChart(String chartId, Callable<Map<String, Integer>> callable) {
super(chartId);
this.callable = callable;
}
@Override
protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
Map<String, Integer> map = callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
return null;
}
boolean allSkipped = true;
for (Map.Entry<String, Integer> entry : map.entrySet()) {
if (entry.getValue() == 0) {
// Skip this invalid
continue;
if (!allSkipped) {
reallyAllSkipped = false;
valuesBuilder.appendField(entryValues.getKey(), valueBuilder.build());
}
allSkipped = false;
valuesBuilder.appendField(entry.getKey(), entry.getValue());
}
if (allSkipped) {
if (reallyAllSkipped) {
// Null = skip the chart
return null;
}
@ -570,6 +505,76 @@ public class Metrics {
}
}
public static class MultiLineChart extends CustomChart {
private final Callable<Map<String, Integer>> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public MultiLineChart(String chartId, Callable<Map<String, Integer>> callable) {
super(chartId);
this.callable = callable;
}
@Override
protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
Map<String, Integer> map = callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
return null;
}
boolean allSkipped = true;
for (Map.Entry<String, Integer> entry : map.entrySet()) {
if (entry.getValue() == 0) {
// Skip this invalid
continue;
}
allSkipped = false;
valuesBuilder.appendField(entry.getKey(), entry.getValue());
}
if (allSkipped) {
// Null = skip the chart
return null;
}
return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build();
}
}
public static class SimpleBarChart extends CustomChart {
private final Callable<Map<String, Integer>> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public SimpleBarChart(String chartId, Callable<Map<String, Integer>> callable) {
super(chartId);
this.callable = callable;
}
@Override
protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
Map<String, Integer> map = callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
return null;
}
for (Map.Entry<String, Integer> entry : map.entrySet()) {
valuesBuilder.appendField(entry.getKey(), new int[] {entry.getValue()});
}
return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build();
}
}
public abstract static class CustomChart {
private final String chartId;
@ -604,32 +609,6 @@ public class Metrics {
protected abstract JsonObjectBuilder.JsonObject getChartData() throws Exception;
}
public static class SingleLineChart extends CustomChart {
private final Callable<Integer> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public SingleLineChart(String chartId, Callable<Integer> callable) {
super(chartId);
this.callable = callable;
}
@Override
protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
int value = callable.call();
if (value == 0) {
// Null = skip the chart
return null;
}
return new JsonObjectBuilder().appendField("value", value).build();
}
}
public static class SimplePie extends CustomChart {
private final Callable<String> callable;
@ -656,9 +635,9 @@ public class Metrics {
}
}
public static class DrilldownPie extends CustomChart {
public static class AdvancedBarChart extends CustomChart {
private final Callable<Map<String, Map<String, Integer>>> callable;
private final Callable<Map<String, int[]>> callable;
/**
* Class constructor.
@ -666,33 +645,29 @@ public class Metrics {
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public DrilldownPie(String chartId, Callable<Map<String, Map<String, Integer>>> callable) {
public AdvancedBarChart(String chartId, Callable<Map<String, int[]>> callable) {
super(chartId);
this.callable = callable;
}
@Override
public JsonObjectBuilder.JsonObject getChartData() throws Exception {
protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
Map<String, Map<String, Integer>> map = callable.call();
Map<String, int[]> map = callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
return null;
}
boolean reallyAllSkipped = true;
for (Map.Entry<String, Map<String, Integer>> entryValues : map.entrySet()) {
JsonObjectBuilder valueBuilder = new JsonObjectBuilder();
boolean allSkipped = true;
for (Map.Entry<String, Integer> valueEntry : map.get(entryValues.getKey()).entrySet()) {
valueBuilder.appendField(valueEntry.getKey(), valueEntry.getValue());
allSkipped = false;
}
if (!allSkipped) {
reallyAllSkipped = false;
valuesBuilder.appendField(entryValues.getKey(), valueBuilder.build());
boolean allSkipped = true;
for (Map.Entry<String, int[]> entry : map.entrySet()) {
if (entry.getValue().length == 0) {
// Skip this invalid
continue;
}
allSkipped = false;
valuesBuilder.appendField(entry.getKey(), entry.getValue());
}
if (reallyAllSkipped) {
if (allSkipped) {
// Null = skip the chart
return null;
}
@ -700,6 +675,32 @@ public class Metrics {
}
}
public static class SingleLineChart extends CustomChart {
private final Callable<Integer> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public SingleLineChart(String chartId, Callable<Integer> callable) {
super(chartId);
this.callable = callable;
}
@Override
protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
int value = callable.call();
if (value == 0) {
// Null = skip the chart
return null;
}
return new JsonObjectBuilder().appendField("value", value).build();
}
}
/**
* An extremely simple JSON builder.
*
@ -905,4 +906,4 @@ public class Metrics {
}
}
}
}
}

View File

@ -34,7 +34,7 @@
<dependency>
<groupId>net.ME1312.SubData</groupId>
<artifactId>Server</artifactId>
<version>21w50a</version>
<version>23w08b</version>
<scope>compile</scope>
</dependency>
<dependency>
@ -126,9 +126,9 @@
<archive>
<manifestFile>src/META-INF/MANIFEST.MF</manifestFile>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<descriptors>
<descriptor>../SubServers.Client/Common/jar-with-some-dependencies.xml</descriptor>
</descriptors>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
<executions>
@ -160,7 +160,7 @@
<reportOutputDirectory>${basedir}/../Javadoc/SubServers.Bungee</reportOutputDirectory>
<additionalOptions>-Xdoclint:none</additionalOptions>
<links>
<link>https://dev.me1312.net/jenkins/job/GalaxiEngine/javadoc/GalaxiUtil/</link>
<link>https://dev.me1312.net/jenkins/job/GalaxiEngine/javadoc/GalaxiBase/</link>
<link>https://dev.me1312.net/jenkins/job/SubData/javadoc/Server/</link>
<link>https://ci.md-5.net/job/BungeeCord/ws/api/target/apidocs/</link>
</links>

View File

@ -1,4 +1,4 @@
Manifest-Version: 1.0
Class-Path: libraries/GalaxiEngine.jar libraries/SubDataServer.jar libraries/BungeeCord.jar
Class-Path: libraries/GalaxiBase.jar libraries/SubDataServer.jar libraries/BungeeCord.jar
Main-Class: net.ME1312.SubServers.Bungee.Launch
Implementation-Title: SubServers.Bungee

View File

@ -36,7 +36,7 @@ public class SubCreateEvent extends Event implements SubEvent, Cancellable {
* @param port Server Port Number
*/
public SubCreateEvent(UUID player, Host host, String name, SubCreator.ServerTemplate template, Version version, int port) {
Util.nullpo(host, name, template, port);
Util.nullpo(host, name, template);
this.player = player;
this.host = host;
this.name = name;

View File

@ -39,7 +39,7 @@ public class SubCreatedEvent extends Event implements SubEvent {
* @param success Success Status
*/
public SubCreatedEvent(UUID player, Host host, String name, SubCreator.ServerTemplate template, Version version, int port, SubServer server, boolean update, boolean success) {
Util.nullpo(host, name, template, port);
Util.nullpo(host, name, template);
this.player = player;
this.host = host;
this.name = name;

View File

@ -110,7 +110,7 @@ public class Executable {
private static boolean terminate9(Object handle) {
try { // Attempt iteration over Java 9 ProcessHandle objects
Class<?> clazz = handle.getClass();
Stream<?> children = (Stream<?>) clazz.getMethod("descendants").invoke(handle);
Stream<?> children = (Stream<?>) clazz.getMethod("children").invoke(handle);
clazz.getMethod("destroyForcibly").invoke(handle);
children.forEach(Executable::terminate9);
return false;

View File

@ -79,8 +79,9 @@ public class ExternalHost extends Host implements ClientHandler {
public void setSubData(DataClient client, int channel) {
if (channel < 0) throw new IllegalArgumentException("Subchannel ID cannot be less than zero");
if (client == null && channel == 0) available = false;
if (client != null || channel == 0) {
if (!subdata.keySet().contains(channel) || (channel == 0 && (client == null || subdata.get(channel) == null))) {
if (!subdata.containsKey(channel) || (channel == 0 && (client == null || subdata.get(channel) == null))) {
subdata.put(channel, (SubDataClient) client);
if (client != null && (client.getHandler() == null || !equals(client.getHandler()))) ((SubDataClient) client).setHandler(this);
}
@ -107,16 +108,27 @@ public class ExternalHost extends Host implements ClientHandler {
client.sendPacket(new PacketOutExReset("Prevent Desync"));
clean = true;
}
HashSet<String> served = new HashSet<String>();
LinkedList<PacketOut> queue = this.queue; this.queue = new LinkedList<PacketOut>();
PacketOut[] payload = new PacketOut[queue.size()];
for (int i = 0; i < payload.length; ++i) {
PacketOut packet = queue.get(i);
if (packet instanceof PacketExAddServer) served.add(((PacketExAddServer) packet).peek());
payload[i] = packet;
}
for (SubServer server : servers.values()) {
client.sendPacket(new PacketExAddServer((ExternalSubServer) server, (server.isRunning())?((ExternalSubLogger) server.getLogger()).getExternalAddress():null, data -> {
if (data.contains(0x0002)) ((ExternalSubServer) server).started(data.getUUID(0x0002));
}));
}
while (queue.size() != 0) {
client.sendPacket(queue.get(0));
queue.remove(0);
if (!served.contains(server.getName())) {
client.sendPacket(new PacketExAddServer((ExternalSubServer) server, (server.isRunning())?((ExternalSubLogger) server.getLogger()).getExternalAddress():null, data -> {
if (data.contains(0x0002)) ((ExternalSubServer) server).started(data.getUUID(0x0002));
else if (server.isRunning()) ((ExternalSubServer) server).stopped(false);
}));
}
}
client.sendPacket(payload);
available = true;
while (this.queue.size() != 0) {
client.sendPacket(this.queue.remove(0));
}
}
@Override
@ -178,8 +190,8 @@ public class ExternalHost extends Host implements ClientHandler {
plugin.getPluginManager().callEvent(event);
if (!event.isCancelled()) {
queue(new PacketExAddServer(((ExternalSubServer) server), (server.isRunning())?((ExternalSubLogger) server.getLogger()).getExternalAddress():null, data -> {
((ExternalSubServer) server).registered(true);
if (data.contains(0x0002)) ((ExternalSubServer) server).started(data.getUUID(0x0002));
((ExternalSubServer) server).registered(true);
}));
servers.put(server.getName().toLowerCase(), server);
return true;

View File

@ -94,7 +94,7 @@ public class ExternalSubCreator extends SubCreator {
@Override
public boolean create(UUID player, String name, ServerTemplate template, Version version, Integer port, Consumer<SubServer> callback) {
Util.nullpo(name, template);
if (host.isAvailable() && host.isEnabled() && template.isEnabled() && !SubAPI.getInstance().getSubServers().keySet().contains(name.toLowerCase()) && !SubCreator.isReserved(name) && (version != null || !template.requiresVersion())) {
if (host.isAvailable() && host.isEnabled() && template.isEnabled() && !SubAPI.getInstance().getSubServers().containsKey(name.toLowerCase()) && !SubCreator.isReserved(name) && (version != null || !template.requiresVersion())) {
StackTraceElement[] origin = new Throwable().getStackTrace();
if (port == null) {
@ -174,7 +174,7 @@ public class ExternalSubCreator extends SubCreator {
Logger.get(prefix).info("Saving...");
SubServer subserver = update;
if (update == null || update.getTemplate() != template || template.getBuildOptions().getBoolean("Update-Settings", false)) {
if (host.plugin.exServers.keySet().contains(name.toLowerCase()))
if (host.plugin.exServers.containsKey(name.toLowerCase()))
host.plugin.exServers.remove(name.toLowerCase());
ObjectMap<String> server = new ObjectMap<String>();
@ -257,7 +257,7 @@ public class ExternalSubCreator extends SubCreator {
@Override
public void terminate(String name) {
if (this.thread.keySet().contains(name.toLowerCase())) {
if (this.thread.containsKey(name.toLowerCase())) {
((SubDataClient) host.getSubData()[0]).sendPacket(new PacketExCreateServer(name.toLowerCase()));
thread.remove(name.toLowerCase());
}
@ -274,7 +274,7 @@ public class ExternalSubCreator extends SubCreator {
@Override
public void waitFor(String name) throws InterruptedException {
while (this.thread.keySet().contains(name.toLowerCase()) && host.getSubData()[0] != null) {
while (this.thread.containsKey(name.toLowerCase()) && host.getSubData()[0] != null) {
Thread.sleep(250);
}
}

View File

@ -151,7 +151,7 @@ public class ExternalSubLogger extends SubLogger {
if (writer != null) {
PrintWriter writer = this.writer;
this.writer = null;
int l = (int) Math.floor((("---------- LOG START \u2014 " + name + " ----------").length() - 9) / 2);
int l = (("---------- LOG START \u2014 " + name + " ----------").length() - 9) / 2;
String s = "";
while (s.length() < l) s += '-';
writer.println(s + " LOG END " + s);

View File

@ -128,6 +128,7 @@ public class ExternalSubServer extends SubServerImpl {
}
void started(UUID address) {
if (!running) {
stopping = false;
started = false;
running = true;
lock = false;
@ -152,14 +153,17 @@ public class ExternalSubServer extends SubServerImpl {
if (!event.isCancelled()) {
history.add(new LoggedCommand(player, stopcmd));
host.queue(new PacketExControlServer(this, Action.STOP));
stopping = true;
return true;
} else return false;
} else return false;
}
private void stopped(Boolean allowrestart) {
void stopped(Boolean allowrestart) {
logger.stop();
history.clear();
started = false;
running = false;
stopping = false;
SubStoppedEvent event = new SubStoppedEvent(this);
host.plugin.getPluginManager().callEvent(event);
Logger.get("SubServers").info(getName() + " has stopped");
@ -205,6 +209,7 @@ public class ExternalSubServer extends SubServerImpl {
host.plugin.getPluginManager().callEvent(event);
if (!event.isCancelled()) {
host.queue(new PacketExControlServer(this, Action.TERMINATE));
stopping = true;
return true;
} else return false;
} else return false;
@ -220,6 +225,7 @@ public class ExternalSubServer extends SubServerImpl {
history.add(new LoggedCommand(player, event.getCommand()));
if (event.getCommand().equalsIgnoreCase(stopcmd)) {
host.queue(new PacketExControlServer(this, Action.STOP));
stopping = true;
} else {
host.queue(new PacketExControlServer(this, Action.COMMAND, event.getCommand()));
}

View File

@ -15,6 +15,7 @@ import net.ME1312.SubServers.Bungee.SubProxy;
import com.dosse.upnp.UPnP;
import com.google.common.collect.Range;
import com.google.gson.Gson;
import java.io.File;
import java.io.FileWriter;
@ -185,7 +186,7 @@ public class InternalHost extends Host {
}
if (!to.exists()) to.mkdirs();
FileWriter writer = new FileWriter(new File(to, "info.json"), false);
writer.write(info.toJSON().toString());
writer.write(new Gson().toJson(info.get()));
writer.close();
} catch (Exception e) {
e.printStackTrace();

View File

@ -64,8 +64,10 @@ public class InternalSubCreator extends SubCreator {
private final int port;
private final String prefix;
private final InternalSubLogger log;
private final LinkedList<String> replace;
private final HashMap<String, String> replacements;
private final Consumer<SubServer> callback;
private boolean install;
private Process process;
private CreatorTask(UUID player, String name, ServerTemplate template, Version version, int port, Consumer<SubServer> callback) {
@ -77,8 +79,10 @@ public class InternalSubCreator extends SubCreator {
this.version = version;
this.port = port;
this.log = new InternalSubLogger(null, this, prefix = name + File.separator + "Creator", InternalSubCreator.this.log, null);
(this.replace = new LinkedList<String>()).add("/server.properties");
this.replacements = new HashMap<String, String>();
this.callback = callback;
this.install = true;
}
private CreatorTask(UUID player, SubServer server, ServerTemplate template, Version version, Consumer<SubServer> callback) {
@ -90,8 +94,10 @@ public class InternalSubCreator extends SubCreator {
this.version = version;
this.port = server.getAddress().getPort();
this.log = new InternalSubLogger(null, this, prefix = name + File.separator + "Updater", InternalSubCreator.this.log, null);
(this.replace = new LinkedList<String>()).add("/server.properties");
this.replacements = new HashMap<String, String>();
this.callback = callback;
this.install = true;
}
private ObjectMap<String> build(File dir, ServerTemplate template, List<ServerTemplate> history, List<ServerTemplate> stack) throws SubCreatorException {
@ -132,6 +138,8 @@ public class InternalSubCreator extends SubCreator {
log.log(INFO, "Loading" + ((template.isDynamic())?" Dynamic":"") + " Template: " + template.getDisplayName());
updateDirectory(template.getDirectory(), dir, template.getBuildOptions().getBoolean("Update-Files", false));
install = template.getBuildOptions().getBoolean("Install-Client", install);
replace.addAll(template.getBuildOptions().getStringList("Replace", Collections.emptyList()));
for (ObjectMapValue<String> replacement : template.getBuildOptions().getMap("Replacements", new ObjectMap<>()).getValues()) if (!replacement.isNull()) {
replacements.put(replacement.getHandle().toLowerCase().replace('-', '_').replace(' ', '_'), replacement.asString());
}
@ -259,12 +267,8 @@ public class InternalSubCreator extends SubCreator {
ReplacementScanner replacements = new ReplacementScanner(this.replacements);
if (config != null) {
try {
if (template.getBuildOptions().getBoolean("Install-Client", true)) generateClient(dir, template.getType(), name);
LinkedList<String> masks = new LinkedList<>();
masks.add("/server.properties");
masks.addAll(template.getBuildOptions().getStringList("Replace", Collections.emptyList()));
replacements.replace(dir, masks.toArray(new String[0]));
if (install) generateClient(dir, template.getType(), name);
replacements.replace(dir, replace.toArray(new String[0]));
} catch (Exception e) {
config = null;
e.printStackTrace();
@ -276,7 +280,7 @@ public class InternalSubCreator extends SubCreator {
Logger.get(prefix).info("Saving...");
SubServer subserver = update;
if (update == null || update.getTemplate() != template || template.getBuildOptions().getBoolean("Update-Settings", false)) {
if (host.plugin.exServers.keySet().contains(name.toLowerCase()))
if (host.plugin.exServers.containsKey(name.toLowerCase()))
host.plugin.exServers.remove(name.toLowerCase());
config = new ObjectMap<String>((Map<String, ?>) replacements.replace(config.get()));
@ -389,7 +393,7 @@ public class InternalSubCreator extends SubCreator {
@Override
public boolean create(UUID player, String name, ServerTemplate template, Version version, Integer port, Consumer<SubServer> callback) {
Util.nullpo(name, template);
if (host.isAvailable() && host.isEnabled() && template.isEnabled() && !SubAPI.getInstance().getSubServers().keySet().contains(name.toLowerCase()) && !SubCreator.isReserved(name) && (version != null || !template.requiresVersion())) {
if (host.isAvailable() && host.isEnabled() && template.isEnabled() && !SubAPI.getInstance().getSubServers().containsKey(name.toLowerCase()) && !SubCreator.isReserved(name) && (version != null || !template.requiresVersion())) {
StackTraceElement[] origin = new Throwable().getStackTrace();
if (port == null) {
@ -470,7 +474,7 @@ public class InternalSubCreator extends SubCreator {
@Override
public void terminate(String name) {
if (this.thread.keySet().contains(name.toLowerCase())) {
if (this.thread.containsKey(name.toLowerCase())) {
if (this.thread.get(name.toLowerCase()).process != null && this.thread.get(name.toLowerCase()).process.isAlive()) {
Executable.terminate(this.thread.get(name.toLowerCase()).process);
} else if (this.thread.get(name.toLowerCase()).isAlive()) {
@ -491,7 +495,7 @@ public class InternalSubCreator extends SubCreator {
@Override
public void waitFor(String name) throws InterruptedException {
while (this.thread.keySet().contains(name.toLowerCase()) && this.thread.get(name.toLowerCase()).isAlive()) {
while (this.thread.containsKey(name.toLowerCase()) && this.thread.get(name.toLowerCase()).isAlive()) {
Thread.sleep(250);
}
}
@ -606,7 +610,7 @@ public class InternalSubCreator extends SubCreator {
YAMLSection config = new YAMLSection();
FileWriter writer = new FileWriter(new File(dir, "subdata.json"), false);
config.setAll(getSubData());
writer.write(config.toJSON().toString());
writer.write(new Gson().toJson(config.get()));
writer.close();
if (!new File(dir, "subdata.rsa.key").exists() && new File("SubServers/subdata.rsa.key").exists()) {

View File

@ -174,7 +174,7 @@ public class InternalSubLogger extends SubLogger {
if (writer != null) {
PrintWriter writer = this.writer;
this.writer = null;
int l = (int) Math.floor((("---------- LOG START \u2014 " + name + " ----------").length() - 9) / 2);
int l = (("---------- LOG START \u2014 " + name + " ----------").length() - 9) / 2;
String s = "";
while (s.length() < l) s += '-';
if (writer != null) {

View File

@ -149,6 +149,7 @@ public class InternalSubServer extends SubServerImpl {
private void run() {
boolean locked = lock;
allowrestart = true;
stopping = false;
started = false;
try {
ProcessBuilder pb = new ProcessBuilder().command(Executable.parse(host.getCreator().getBashDirectory(), executable)).directory(directory);
@ -181,6 +182,8 @@ public class InternalSubServer extends SubServerImpl {
Logger.get("SubServers").info(getName() + " has stopped");
process = null;
command = null;
started = false;
stopping = false;
history.clear();
SubStoppedEvent event = new SubStoppedEvent(this);
@ -245,6 +248,7 @@ public class InternalSubServer extends SubServerImpl {
host.plugin.getPluginManager().callEvent(event);
if (!event.isCancelled()) {
try {
stopping = true;
allowrestart = false;
history.add(new LoggedCommand(player, stopcmd));
if (process != null && process.isAlive()) {
@ -267,6 +271,7 @@ public class InternalSubServer extends SubServerImpl {
SubStopEvent event = new SubStopEvent(player, this, true);
host.plugin.getPluginManager().callEvent(event);
if (!event.isCancelled()) {
stopping = true;
allowrestart = false;
if (process != null && process.isAlive()) Executable.terminate(process);
return true;
@ -282,7 +287,10 @@ public class InternalSubServer extends SubServerImpl {
host.plugin.getPluginManager().callEvent(event);
if (!event.isCancelled() && (player == null || !DISALLOWED_COMMANDS.matcher(command).find())) {
try {
if (event.getCommand().equalsIgnoreCase(stopcmd)) allowrestart = false;
if (event.getCommand().equalsIgnoreCase(stopcmd)) {
stopping = true;
allowrestart = false;
}
history.add(new LoggedCommand(player, event.getCommand()));
if (process != null && process.isAlive()) {
this.command.write(event.getCommand());

View File

@ -50,7 +50,7 @@ public class Proxy implements ClientHandler, ExtraDataHandler<String> {
boolean update = false;
if (channel < 0) throw new IllegalArgumentException("Subchannel ID cannot be less than zero");
if (client != null || channel == 0) {
if (!subdata.keySet().contains(channel) || (channel == 0 && (client == null || subdata.get(channel) == null))) {
if (!subdata.containsKey(channel) || (channel == 0 && (client == null || subdata.get(channel) == null))) {
update = true;
subdata.put(channel, client);
if (client != null && (client.getHandler() == null || !equals(client.getHandler()))) client.setHandler(this);

View File

@ -105,7 +105,7 @@ public class ServerImpl extends BungeeServerInfo implements Server {
boolean update = false;
if (channel < 0) throw new IllegalArgumentException("Subchannel ID cannot be less than zero");
if (client != null || channel == 0) {
if (!subdata.keySet().contains(channel) || (channel == 0 && (client == null || subdata.get(channel) == null))) {
if (!subdata.containsKey(channel) || (channel == 0 && (client == null || subdata.get(channel) == null))) {
update = true;
subdata.put(channel, (SubDataClient) client);
if (client != null && (client.getHandler() == null || !equals(client.getHandler()))) ((SubDataClient) client).setHandler(this);

View File

@ -217,6 +217,14 @@ public interface SubServer extends Server {
*/
boolean isOnline();
/**
* If the Server is Stopping<br>
* <b>This method can only be true when the server is stopped through the server manager!</b>
*
* @return Stopping Status
*/
boolean isStopping();
/**
* Grabs the Host of the Server
*

View File

@ -22,7 +22,7 @@ public abstract class SubServerImpl extends ServerImpl implements SubServer {
private List<Pair<String, String>> incompatibilities = new ArrayList<Pair<String, String>>();
private SubCreator.ServerTemplate templateV = null;
private String templateS = null;
protected boolean registered, started, updating;
protected boolean registered, started, stopping, updating;
/**
* Creates a SubServer
@ -93,6 +93,11 @@ public abstract class SubServerImpl extends ServerImpl implements SubServer {
return isRunning() && started;
}
@Override
public boolean isStopping() {
return isRunning() && stopping;
}
@Override
public void setTemplate(String template) {
this.templateV = null;
@ -109,7 +114,7 @@ public abstract class SubServerImpl extends ServerImpl implements SubServer {
public SubCreator.ServerTemplate getTemplate() {
if (templateV != null) {
return templateV;
} else if (templateS != null && getHost().getCreator().getTemplates().keySet().contains(templateS.toLowerCase())) {
} else if (templateS != null && getHost().getCreator().getTemplates().containsKey(templateS.toLowerCase())) {
return getHost().getCreator().getTemplate(templateS.toLowerCase());
} else {
return null;
@ -183,6 +188,7 @@ public abstract class SubServerImpl extends ServerImpl implements SubServer {
sinfo.set("exec", getExecutable());
sinfo.set("running", isRunning());
sinfo.set("online", isOnline());
sinfo.set("stopping", isStopping());
sinfo.set("stop-cmd", getStopCommand());
sinfo.set("stop-action", getStopAction().toString());
sinfo.set("auto-run", SubAPI.getInstance().getInternals().servers.get().getMap("Servers").getMap(getName(), new ObjectMap<String>()).getBoolean("Run-On-Launch", false));

View File

@ -82,38 +82,38 @@ public final class Launch {
System.out.println("*******************************************");
}
System.out.println("");
}
SubProxy plugin = new SubProxy(System.out, patched);
net.md_5.bungee.api.ProxyServer.class.getMethod("setInstance", net.md_5.bungee.api.ProxyServer.class).invoke(null, plugin);
plugin.getLogger().info("Enabled " + plugin.getBungeeName() + " version " + plugin.getVersion());
plugin.start();
SubProxy plugin = new SubProxy(System.out, patched);
net.md_5.bungee.api.ProxyServer.class.getMethod("setInstance", net.md_5.bungee.api.ProxyServer.class).invoke(null, plugin);
plugin.getLogger().info("Enabled " + plugin.getBungeeName() + " version " + plugin.getVersion());
plugin.start();
if (!options.has("noconsole")) {
try {
if (Try.all.get(() -> Class.forName("io.github.waterfallmc.waterfall.console.WaterfallConsole").getMethod("readCommands") != null, false)) { // Waterfall Setup
Class.forName("io.github.waterfallmc.waterfall.console.WaterfallConsole").getMethod("readCommands").invoke(null);
} else if (Try.all.get(() -> Class.forName("io.github.waterfallmc.waterfall.console.WaterfallConsole").getMethod("start") != null, false)) {
Class console = Class.forName("io.github.waterfallmc.waterfall.console.WaterfallConsole");
console.getMethod("start").invoke(console.getConstructor().newInstance());
} else {
plugin.canSudo = true;
String line;
while (plugin.isRunning && (line = plugin.getConsoleReader().readLine(">")) != null) {
if (plugin.sudo == null) {
if (!plugin.getPluginManager().dispatchCommand(net.md_5.bungee.command.ConsoleCommandSender.class.cast(net.md_5.bungee.command.ConsoleCommandSender.class.getMethod("getInstance").invoke(null)), line)) {
plugin.getConsole().sendMessage(net.md_5.bungee.api.ChatColor.RED + "Command not found");
if (!options.has("noconsole")) {
try {
if (Try.all.get(() -> Class.forName("io.github.waterfallmc.waterfall.console.WaterfallConsole").getMethod("readCommands") != null, false)) { // Waterfall Setup
Class.forName("io.github.waterfallmc.waterfall.console.WaterfallConsole").getMethod("readCommands").invoke(null);
} else if (Try.all.get(() -> Class.forName("io.github.waterfallmc.waterfall.console.WaterfallConsole").getMethod("start") != null, false)) {
Class console = Class.forName("io.github.waterfallmc.waterfall.console.WaterfallConsole");
console.getMethod("start").invoke(console.getConstructor().newInstance());
} else {
plugin.canSudo = true;
String line;
while (plugin.isRunning && (line = plugin.getConsoleReader().readLine(">")) != null) {
if (plugin.sudo == null) {
if (!plugin.getPluginManager().dispatchCommand(net.md_5.bungee.command.ConsoleCommandSender.class.cast(net.md_5.bungee.command.ConsoleCommandSender.class.getMethod("getInstance").invoke(null)), line)) {
plugin.getConsole().sendMessage(net.md_5.bungee.api.ChatColor.RED + "Command not found");
}
} else if (line.equalsIgnoreCase("exit")) {
plugin.sudo = null;
net.ME1312.SubServers.Bungee.Library.Compatibility.Logger.get("SubServers").info("Reverting to the BungeeCord Console");
} else {
plugin.sudo.command(line);
}
} else if (line.equalsIgnoreCase("exit")) {
plugin.sudo = null;
net.ME1312.SubServers.Bungee.Library.Compatibility.Logger.get("SubServers").info("Reverting to the BungeeCord Console");
} else {
plugin.sudo.command(line);
}
}
} catch (NoSuchMethodError | NoSuchMethodException e) {
plugin.getLogger().warning("Standard BungeeCord console not found; Console commands may now be disabled.");
}
} catch (NoSuchMethodError | NoSuchMethodException e) {
plugin.getLogger().warning("Standard BungeeCord console not found; Console commands may now be disabled.");
}
}
}

View File

@ -4,12 +4,16 @@ package net.ME1312.SubServers.Bungee.Library.Compatibility;
import net.ME1312.SubServers.Bungee.SubAPI;
import com.google.common.io.Resources;
import net.md_5.bungee.api.ProxyServer;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.logging.Logger;
import static java.util.logging.Level.SEVERE;
/**
* JNA Library Loader Class
@ -29,12 +33,13 @@ public class JNA {
public static ClassLoader get() {
if (JNA == null) {
boolean announced = false;
Logger log = ProxyServer.getInstance().getLogger();
File library = new File(SubAPI.getInstance().getInternals().dir, "SubServers/Cache/Libraries");
File jna = new File(library, "jna-" + JNA_VERSION + ".jar");
jna.getParentFile().mkdirs();
if (!jna.exists()) {
announced = true;
System.out.println(">> Downloading JNA Library v" + JNA_VERSION);
log.info(">> Downloading JNA v" + JNA_VERSION);
try (FileOutputStream fin = new FileOutputStream(jna)) {
Resources.copy(new URL(JNA_DOWNLOAD.replace("$1", "jna")), fin);
} catch (Throwable e) {
@ -45,7 +50,7 @@ public class JNA {
File platform = new File(library, "jna-platform-" + JNA_VERSION + ".jar");
platform.getParentFile().mkdirs();
if (!platform.exists()) {
if (!announced) System.out.println(">> Downloading JNA Library v" + JNA_VERSION);
if (!announced) log.info(">> Downloading JNA platform v" + JNA_VERSION);
announced = true;
try (FileOutputStream fin = new FileOutputStream(platform)) {
Resources.copy(new URL(JNA_DOWNLOAD.replace("$1", "jna-platform")), fin);
@ -55,16 +60,14 @@ public class JNA {
}
}
if (jna.exists() && platform.exists()) {
if (announced) System.out.println(">> Loading JNA Library");
if (announced) log.info(">> JNA download complete");
try {
JNA = new URLClassLoader(new URL[]{jna.toURI().toURL(), platform.toURI().toURL()});
} catch (Throwable e) {
System.out.println(">> Could not load JNA Library:");
e.printStackTrace();
log.log(SEVERE, ">> Couldn't load JNA:", e);
}
} else {
System.out.println(">> Could not load JNA Library:");
new FileNotFoundException().printStackTrace();
log.log(SEVERE, ">> Couldn't load JNA:", new FileNotFoundException());
}
}
return JNA;

View File

@ -324,9 +324,12 @@ public class ConfigUpdater {
existing = updated.clone();
i++;
} if (was.compareTo(new Version("21w49b")) <= 0) {
} if (was.compareTo(new Version("22w07c")) <= 0) {
if (existing.contains("Lang")) {
updated.getMap("Lang").remove("Command.Teleport");
}
//existing = updated.clone();
existing = updated.clone();
i++;
}// if (was.compareTo(new Version("99w99a")) <= 0) {
// // do something
@ -358,6 +361,13 @@ public class ConfigUpdater {
def.put("Bungee.List.List", "&f$str$");
def.put("Bungee.List.Divider", "&f, ");
def.put("Bungee.List.Total", "Total players online: $int$");
def.put("Signs.Create", "&aSubServers &2&l\\u00BB&a Server sign activated");
def.put("Signs.Delete", "&aSubServers &2&l\\u00BB&a Server sign removed");
def.put("Signs.Text.Unknown", "&f&oSubServers\\n&3$str$\\n&7Unknown Status\\n&8\\u2022 \\u2022 \\u2022 \\u2022 \\u2022 \\u2022 \\u2022");
def.put("Signs.Text.Offline", "&c&oSubServers\\n&3$str$\\n&4Offline\\n&7Click to Start");
def.put("Signs.Text.Starting", "&e&oSubServers\\n&3$str$\\n&6Starting\\n&8\\u2022 \\u2022 \\u2022 \\u2022 \\u2022 \\u2022 \\u2022");
def.put("Signs.Text.Online", "&a&oSubServers\\n&3$str$\\n&2$int$ Online\\n&7Click to Join");
def.put("Signs.Text.Stopping", "&e&oSubServers\\n&3$str$\\n&6Stopping\\n&8\\u2022 \\u2022 \\u2022 \\u2022 \\u2022 \\u2022 \\u2022");
def.put("Command.Generic.Player-Only", "&cSubServers &4&l\\u00BB&c The console cannot perform this command");
def.put("Command.Generic.Console-Only", "&cSubServers &4&l\\u00BB&c This command is for console use only");
def.put("Command.Generic.Usage", "&7SubServers &8&l\\u00BB&7 Usage: &f$str$");
@ -457,7 +467,8 @@ public class ConfigUpdater {
def.put("Command.Delete.Disappeared", "&cSubServers &4&l\\u00BB&c Subserver &4$str$&c has disappeared");
def.put("Command.Delete.Running", "&cSubServers &4&l\\u00BB&c Cannot delete &4$str$&c while it is still running");
def.put("Command.Delete", "&aSubServers &2&l\\u00BB&a Deleting &2$int$&a subserver(s)");
def.put("Command.Teleport", "&aSubServers &2&l\\u00BB&a Teleporting &2$str$&a to server");
def.put("Command.Teleport", "&aSubServers &2&l\\u00BB&a Teleporting to &2$str$");
def.put("Command.Teleport.Others", "&aSubServers &2&l\\u00BB&a Teleporting &2$name$&a to &2$str$");
def.put("Command.Teleport.Not-Running", "&cSubServers &4&l\\u00BB&c Subserver &4$str$&c is not running");
def.put("Interface.Generic.Back", "&cBack");
def.put("Interface.Generic.Back-Arrow", "&e&l<--");

View File

@ -74,9 +74,6 @@ public abstract class FileScanner {
literal = new StringBuilder();
}
switch (c) {
case '\\':
if (i.hasNext()) c = i.next();
literal.appendCodePoint(c);
case '[':
for (boolean escaped = false; i.hasNext() && (c != ']' || escaped); c = i.next()) {
if (c == '\\') escaped = !escaped;
@ -95,6 +92,8 @@ public abstract class FileScanner {
case '?':
rule.append("[^/]");
break;
case '\\':
if (i.hasNext()) c = i.next();
default:
literal.appendCodePoint(c);
break;

View File

@ -1,917 +0,0 @@
package net.ME1312.SubServers.Bungee.Library;
import net.ME1312.SubData.Server.DataServer;
import net.ME1312.SubServers.Bungee.BungeeCommon;
import net.ME1312.SubServers.Bungee.SubAPI;
import gnu.trove.map.hash.TIntObjectHashMap;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.plugin.Plugin;
import net.md_5.bungee.config.Configuration;
import net.md_5.bungee.config.ConfigurationProvider;
import net.md_5.bungee.config.YamlConfiguration;
import net.md_5.bungee.protocol.ProtocolConstants;
import javax.net.ssl.HttpsURLConnection;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.logging.Level;
import java.util.stream.Collectors;
import java.util.zip.GZIPOutputStream;
public class Metrics {
private final Plugin plugin;
private final MetricsBase metricsBase;
private boolean enabled;
private String serverUUID;
private boolean logErrors = false;
private boolean logSentData;
private boolean logResponseStatusText;
/**
* Creates a new Metrics instance.
*
* @param plugin Your plugin instance.
* @param serviceId The id of the service. It can be found at <a
* href="https://bstats.org/what-is-my-plugin-id">What is my plugin id?</a>
*/
public Metrics(Plugin plugin, int serviceId) {
this.plugin = plugin;
try {
loadConfig();
} catch (IOException e) {
// Failed to load configuration
plugin.getLogger().log(Level.WARNING, "Failed to load bStats config!", e);
metricsBase = null;
return;
}
metricsBase =
new MetricsBase(
"bungeecord",
serverUUID,
serviceId,
enabled,
this::appendPlatformData,
this::appendServiceData,
null,
() -> true,
(message, error) -> this.plugin.getLogger().log(Level.WARNING, message, error),
(message) -> this.plugin.getLogger().log(Level.INFO, message),
logErrors,
logSentData,
logResponseStatusText);
}
/** Loads the bStats configuration. */
private void loadConfig() throws IOException {
File bStatsFolder = new File(plugin.getDataFolder().getParentFile(), "bStats");
bStatsFolder.mkdirs();
File configFile = new File(bStatsFolder, "config.yml");
if (!configFile.exists()) {
writeFile(
configFile,
"# bStats (https://bStats.org) collects some basic information for plugin authors, like how",
"# many people use their plugin and their total player count. It's recommended to keep bStats",
"# enabled, but if you're not comfortable with this, you can turn this setting off. There is no",
"# performance penalty associated with having metrics enabled, and data sent to bStats is fully",
"# anonymous.",
"enabled: true",
"serverUuid: \"" + UUID.randomUUID() + "\"",
"logFailedRequests: false",
"logSentData: false",
"logResponseStatusText: false");
}
Configuration configuration =
ConfigurationProvider.getProvider(YamlConfiguration.class).load(configFile);
// Load configuration
enabled = configuration.getBoolean("enabled", true);
serverUUID = configuration.getString("serverUuid");
logErrors = configuration.getBoolean("logFailedRequests", false);
logSentData = configuration.getBoolean("logSentData", false);
logResponseStatusText = configuration.getBoolean("logResponseStatusText", false);
}
private void writeFile(File file, String... lines) throws IOException {
try (BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(file))) {
for (String line : lines) {
bufferedWriter.write(line);
bufferedWriter.newLine();
}
}
}
/**
* Adds a custom chart.
*
* @param chart The chart to add.
*/
public void addCustomChart(CustomChart chart) {
metricsBase.addCustomChart(chart);
}
private static final AdvancedPie PLAYER_VERSIONS;
static {
final int[] PROTOCOL_VERSIONS;
final String[] PROTOCOL_NAMES;
{
TIntObjectHashMap<String> protocols = new TIntObjectHashMap<String>();
try {
for (Field f : ProtocolConstants.class.getDeclaredFields()) {
int fm = f.getModifiers();
if (Modifier.isPublic(fm) && Modifier.isStatic(fm) && Modifier.isFinal(fm) && f.getType() == int.class && f.getName().startsWith("MINECRAFT_")) {
protocols.put(f.getInt(null), f.getName().substring(10).replace('_', '.'));
}
}
} catch (Throwable e) {
e.printStackTrace();
}
PROTOCOL_VERSIONS = protocols.keys();
PROTOCOL_NAMES = new String[PROTOCOL_VERSIONS.length];
Arrays.sort(PROTOCOL_VERSIONS);
for (int i = 0; i < PROTOCOL_VERSIONS.length; ++i) {
PROTOCOL_NAMES[i] = protocols.get(PROTOCOL_VERSIONS[i]);
}
}
PLAYER_VERSIONS = new AdvancedPie("player_versions", () -> {
int[] players = new int[PROTOCOL_VERSIONS.length];
for (ProxiedPlayer player : ProxyServer.getInstance().getPlayers()) {
int i = Arrays.binarySearch(PROTOCOL_VERSIONS, player.getPendingConnection().getVersion());
if (i != -1) {
++players[i];
}
}
HashMap<String, Integer> map = new HashMap<String, Integer>();
for (int i = 0; i < PROTOCOL_NAMES.length; ++i) if (players[i] != 0) {
map.put(PROTOCOL_NAMES[i], players[i]);
}
return map;
});
}
public void appendAppData() {
addCustomChart(new SingleLineChart("managed_hosts", () -> {
return SubAPI.getInstance().getHosts().size();
}));
addCustomChart(new SingleLineChart("subdata_connected", () -> {
DataServer subdata = SubAPI.getInstance().getSubDataNetwork();
return (subdata != null)? subdata.getClients().size() : 0;
}));
addCustomChart(PLAYER_VERSIONS);
}
public void appendPluginData() {
addCustomChart(new SimplePie("subservers_version", () -> {
return SubAPI.getInstance().getWrapperVersion().toString();
}));
addCustomChart(PLAYER_VERSIONS);
}
private void appendPlatformData(JsonObjectBuilder builder) {
builder.appendField("playerAmount", plugin.getProxy().getOnlineCount());
builder.appendField("managedServers", ((BungeeCommon) plugin.getProxy()).getServersCopy().size());
builder.appendField("onlineMode", plugin.getProxy().getConfig().isOnlineMode() ? 1 : 0);
builder.appendField("bungeecordVersion", plugin.getProxy().getVersion());
builder.appendField("javaVersion", System.getProperty("java.version"));
builder.appendField("osName", System.getProperty("os.name"));
builder.appendField("osArch", System.getProperty("os.arch"));
builder.appendField("osVersion", System.getProperty("os.version"));
builder.appendField("coreCount", Runtime.getRuntime().availableProcessors());
}
private void appendServiceData(JsonObjectBuilder builder) {
builder.appendField("pluginVersion", plugin.getDescription().getVersion());
}
public static class MetricsBase {
/** The version of the Metrics class. */
public static final String METRICS_VERSION = "2.2.1";
private static final ScheduledExecutorService scheduler =
Executors.newScheduledThreadPool(1, task -> new Thread(task, "bStats-Metrics"));
private static final String REPORT_URL = "https://bStats.org/api/v2/data/%s";
private final String platform;
private final String serverUuid;
private final int serviceId;
private final Consumer<JsonObjectBuilder> appendPlatformDataConsumer;
private final Consumer<JsonObjectBuilder> appendServiceDataConsumer;
private final Consumer<Runnable> submitTaskConsumer;
private final Supplier<Boolean> checkServiceEnabledSupplier;
private final BiConsumer<String, Throwable> errorLogger;
private final Consumer<String> infoLogger;
private final boolean logErrors;
private final boolean logSentData;
private final boolean logResponseStatusText;
private final Set<CustomChart> customCharts = new HashSet<>();
private final boolean enabled;
/**
* Creates a new MetricsBase class instance.
*
* @param platform The platform of the service.
* @param serviceId The id of the service.
* @param serverUuid The server uuid.
* @param enabled Whether or not data sending is enabled.
* @param appendPlatformDataConsumer A consumer that receives a {@code JsonObjectBuilder} and
* appends all platform-specific data.
* @param appendServiceDataConsumer A consumer that receives a {@code JsonObjectBuilder} and
* appends all service-specific data.
* @param submitTaskConsumer A consumer that takes a runnable with the submit task. This can be
* used to delegate the data collection to a another thread to prevent errors caused by
* concurrency. Can be {@code null}.
* @param checkServiceEnabledSupplier A supplier to check if the service is still enabled.
* @param errorLogger A consumer that accepts log message and an error.
* @param infoLogger A consumer that accepts info log messages.
* @param logErrors Whether or not errors should be logged.
* @param logSentData Whether or not the sent data should be logged.
* @param logResponseStatusText Whether or not the response status text should be logged.
*/
public MetricsBase(
String platform,
String serverUuid,
int serviceId,
boolean enabled,
Consumer<JsonObjectBuilder> appendPlatformDataConsumer,
Consumer<JsonObjectBuilder> appendServiceDataConsumer,
Consumer<Runnable> submitTaskConsumer,
Supplier<Boolean> checkServiceEnabledSupplier,
BiConsumer<String, Throwable> errorLogger,
Consumer<String> infoLogger,
boolean logErrors,
boolean logSentData,
boolean logResponseStatusText) {
this.platform = platform;
this.serverUuid = serverUuid;
this.serviceId = serviceId;
this.enabled = enabled;
this.appendPlatformDataConsumer = appendPlatformDataConsumer;
this.appendServiceDataConsumer = appendServiceDataConsumer;
this.submitTaskConsumer = submitTaskConsumer;
this.checkServiceEnabledSupplier = checkServiceEnabledSupplier;
this.errorLogger = errorLogger;
this.infoLogger = infoLogger;
this.logErrors = logErrors;
this.logSentData = logSentData;
this.logResponseStatusText = logResponseStatusText;
checkRelocation();
if (enabled) {
startSubmitting();
}
}
public void addCustomChart(CustomChart chart) {
this.customCharts.add(chart);
}
private void startSubmitting() {
final Runnable submitTask =
() -> {
if (!enabled || !checkServiceEnabledSupplier.get()) {
// Submitting data or service is disabled
scheduler.shutdown();
return;
}
if (submitTaskConsumer != null) {
submitTaskConsumer.accept(this::submitData);
} else {
this.submitData();
}
};
// Many servers tend to restart at a fixed time at xx:00 which causes an uneven distribution
// of requests on the
// bStats backend. To circumvent this problem, we introduce some randomness into the initial
// and second delay.
// WARNING: You must not modify and part of this Metrics class, including the submit delay or
// frequency!
// WARNING: Modifying this code will get your plugin banned on bStats. Just don't do it!
long initialDelay = (long) (1000 * 60 * (3 + Math.random() * 3));
long secondDelay = (long) (1000 * 60 * (Math.random() * 30));
scheduler.schedule(submitTask, initialDelay, TimeUnit.MILLISECONDS);
scheduler.scheduleAtFixedRate(
submitTask, initialDelay + secondDelay, 1000 * 60 * 30, TimeUnit.MILLISECONDS);
}
private void submitData() {
final JsonObjectBuilder baseJsonBuilder = new JsonObjectBuilder();
appendPlatformDataConsumer.accept(baseJsonBuilder);
final JsonObjectBuilder serviceJsonBuilder = new JsonObjectBuilder();
appendServiceDataConsumer.accept(serviceJsonBuilder);
JsonObjectBuilder.JsonObject[] chartData =
customCharts.stream()
.map(customChart -> customChart.getRequestJsonObject(errorLogger, logErrors))
.filter(Objects::nonNull)
.toArray(JsonObjectBuilder.JsonObject[]::new);
serviceJsonBuilder.appendField("id", serviceId);
serviceJsonBuilder.appendField("customCharts", chartData);
baseJsonBuilder.appendField("service", serviceJsonBuilder.build());
baseJsonBuilder.appendField("serverUUID", serverUuid);
baseJsonBuilder.appendField("metricsVersion", METRICS_VERSION);
JsonObjectBuilder.JsonObject data = baseJsonBuilder.build();
scheduler.execute(
() -> {
try {
// Send the data
sendData(data);
} catch (Exception e) {
// Something went wrong! :(
if (logErrors) {
errorLogger.accept("Could not submit bStats metrics data", e);
}
}
});
}
private void sendData(JsonObjectBuilder.JsonObject data) throws Exception {
if (logSentData) {
infoLogger.accept("Sent bStats metrics data: " + data.toString());
}
String url = String.format(REPORT_URL, platform);
HttpsURLConnection connection = (HttpsURLConnection) new URL(url).openConnection();
// Compress the data to save bandwidth
byte[] compressedData = compress(data.toString());
connection.setRequestMethod("POST");
connection.addRequestProperty("Accept", "application/json");
connection.addRequestProperty("Connection", "close");
connection.addRequestProperty("Content-Encoding", "gzip");
connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length));
connection.setRequestProperty("Content-Type", "application/json");
connection.setRequestProperty("User-Agent", "Metrics-Service/1");
connection.setDoOutput(true);
try (DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream())) {
outputStream.write(compressedData);
}
StringBuilder builder = new StringBuilder();
try (BufferedReader bufferedReader =
new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
String line;
while ((line = bufferedReader.readLine()) != null) {
builder.append(line);
}
}
if (logResponseStatusText) {
infoLogger.accept("Sent data to bStats and received response: " + builder);
}
}
/** Checks that the class was properly relocated. */
private void checkRelocation() {
// You can use the property to disable the check in your test environment
if (System.getProperty("bstats.relocatecheck") == null
|| !System.getProperty("bstats.relocatecheck").equals("false")) {
// Maven's Relocate is clever and changes strings, too. So we have to use this little
// "trick" ... :D
final String defaultPackage =
new String(new byte[] {'o', 'r', 'g', '.', 'b', 's', 't', 'a', 't', 's'});
final String examplePackage =
new String(new byte[] {'y', 'o', 'u', 'r', '.', 'p', 'a', 'c', 'k', 'a', 'g', 'e'});
// We want to make sure no one just copy & pastes the example and uses the wrong package
// names
if (MetricsBase.class.getPackage().getName().startsWith(defaultPackage)
|| MetricsBase.class.getPackage().getName().startsWith(examplePackage)) {
throw new IllegalStateException("bStats Metrics class has not been relocated correctly!");
}
}
}
/**
* Gzips the given string.
*
* @param str The string to gzip.
* @return The gzipped string.
*/
private static byte[] compress(final String str) throws IOException {
if (str == null) {
return null;
}
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try (GZIPOutputStream gzip = new GZIPOutputStream(outputStream)) {
gzip.write(str.getBytes(StandardCharsets.UTF_8));
}
return outputStream.toByteArray();
}
}
public static class AdvancedBarChart extends CustomChart {
private final Callable<Map<String, int[]>> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public AdvancedBarChart(String chartId, Callable<Map<String, int[]>> callable) {
super(chartId);
this.callable = callable;
}
@Override
protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
Map<String, int[]> map = callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
return null;
}
boolean allSkipped = true;
for (Map.Entry<String, int[]> entry : map.entrySet()) {
if (entry.getValue().length == 0) {
// Skip this invalid
continue;
}
allSkipped = false;
valuesBuilder.appendField(entry.getKey(), entry.getValue());
}
if (allSkipped) {
// Null = skip the chart
return null;
}
return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build();
}
}
public static class SimpleBarChart extends CustomChart {
private final Callable<Map<String, Integer>> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public SimpleBarChart(String chartId, Callable<Map<String, Integer>> callable) {
super(chartId);
this.callable = callable;
}
@Override
protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
Map<String, Integer> map = callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
return null;
}
for (Map.Entry<String, Integer> entry : map.entrySet()) {
valuesBuilder.appendField(entry.getKey(), new int[] {entry.getValue()});
}
return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build();
}
}
public static class MultiLineChart extends CustomChart {
private final Callable<Map<String, Integer>> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public MultiLineChart(String chartId, Callable<Map<String, Integer>> callable) {
super(chartId);
this.callable = callable;
}
@Override
protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
Map<String, Integer> map = callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
return null;
}
boolean allSkipped = true;
for (Map.Entry<String, Integer> entry : map.entrySet()) {
if (entry.getValue() == 0) {
// Skip this invalid
continue;
}
allSkipped = false;
valuesBuilder.appendField(entry.getKey(), entry.getValue());
}
if (allSkipped) {
// Null = skip the chart
return null;
}
return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build();
}
}
public static class AdvancedPie extends CustomChart {
private final Callable<Map<String, Integer>> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public AdvancedPie(String chartId, Callable<Map<String, Integer>> callable) {
super(chartId);
this.callable = callable;
}
@Override
protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
Map<String, Integer> map = callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
return null;
}
boolean allSkipped = true;
for (Map.Entry<String, Integer> entry : map.entrySet()) {
if (entry.getValue() == 0) {
// Skip this invalid
continue;
}
allSkipped = false;
valuesBuilder.appendField(entry.getKey(), entry.getValue());
}
if (allSkipped) {
// Null = skip the chart
return null;
}
return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build();
}
}
public abstract static class CustomChart {
private final String chartId;
protected CustomChart(String chartId) {
if (chartId == null) {
throw new IllegalArgumentException("chartId must not be null");
}
this.chartId = chartId;
}
public JsonObjectBuilder.JsonObject getRequestJsonObject(
BiConsumer<String, Throwable> errorLogger, boolean logErrors) {
JsonObjectBuilder builder = new JsonObjectBuilder();
builder.appendField("chartId", chartId);
try {
JsonObjectBuilder.JsonObject data = getChartData();
if (data == null) {
// If the data is null we don't send the chart.
return null;
}
builder.appendField("data", data);
} catch (Throwable t) {
if (logErrors) {
errorLogger.accept("Failed to get data for custom chart with id " + chartId, t);
}
return null;
}
return builder.build();
}
protected abstract JsonObjectBuilder.JsonObject getChartData() throws Exception;
}
public static class SingleLineChart extends CustomChart {
private final Callable<Integer> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public SingleLineChart(String chartId, Callable<Integer> callable) {
super(chartId);
this.callable = callable;
}
@Override
protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
int value = callable.call();
if (value == 0) {
// Null = skip the chart
return null;
}
return new JsonObjectBuilder().appendField("value", value).build();
}
}
public static class SimplePie extends CustomChart {
private final Callable<String> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public SimplePie(String chartId, Callable<String> callable) {
super(chartId);
this.callable = callable;
}
@Override
protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
String value = callable.call();
if (value == null || value.isEmpty()) {
// Null = skip the chart
return null;
}
return new JsonObjectBuilder().appendField("value", value).build();
}
}
public static class DrilldownPie extends CustomChart {
private final Callable<Map<String, Map<String, Integer>>> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public DrilldownPie(String chartId, Callable<Map<String, Map<String, Integer>>> callable) {
super(chartId);
this.callable = callable;
}
@Override
public JsonObjectBuilder.JsonObject getChartData() throws Exception {
JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
Map<String, Map<String, Integer>> map = callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
return null;
}
boolean reallyAllSkipped = true;
for (Map.Entry<String, Map<String, Integer>> entryValues : map.entrySet()) {
JsonObjectBuilder valueBuilder = new JsonObjectBuilder();
boolean allSkipped = true;
for (Map.Entry<String, Integer> valueEntry : map.get(entryValues.getKey()).entrySet()) {
valueBuilder.appendField(valueEntry.getKey(), valueEntry.getValue());
allSkipped = false;
}
if (!allSkipped) {
reallyAllSkipped = false;
valuesBuilder.appendField(entryValues.getKey(), valueBuilder.build());
}
}
if (reallyAllSkipped) {
// Null = skip the chart
return null;
}
return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build();
}
}
/**
* An extremely simple JSON builder.
*
* <p>While this class is neither feature-rich nor the most performant one, it's sufficient enough
* for its use-case.
*/
public static class JsonObjectBuilder {
private StringBuilder builder = new StringBuilder();
private boolean hasAtLeastOneField = false;
public JsonObjectBuilder() {
builder.append("{");
}
/**
* Appends a null field to the JSON.
*
* @param key The key of the field.
* @return A reference to this object.
*/
public JsonObjectBuilder appendNull(String key) {
appendFieldUnescaped(key, "null");
return this;
}
/**
* Appends a string field to the JSON.
*
* @param key The key of the field.
* @param value The value of the field.
* @return A reference to this object.
*/
public JsonObjectBuilder appendField(String key, String value) {
if (value == null) {
throw new IllegalArgumentException("JSON value must not be null");
}
appendFieldUnescaped(key, "\"" + escape(value) + "\"");
return this;
}
/**
* Appends an integer field to the JSON.
*
* @param key The key of the field.
* @param value The value of the field.
* @return A reference to this object.
*/
public JsonObjectBuilder appendField(String key, int value) {
appendFieldUnescaped(key, String.valueOf(value));
return this;
}
/**
* Appends an object to the JSON.
*
* @param key The key of the field.
* @param object The object.
* @return A reference to this object.
*/
public JsonObjectBuilder appendField(String key, JsonObject object) {
if (object == null) {
throw new IllegalArgumentException("JSON object must not be null");
}
appendFieldUnescaped(key, object.toString());
return this;
}
/**
* Appends a string array to the JSON.
*
* @param key The key of the field.
* @param values The string array.
* @return A reference to this object.
*/
public JsonObjectBuilder appendField(String key, String[] values) {
if (values == null) {
throw new IllegalArgumentException("JSON values must not be null");
}
String escapedValues =
Arrays.stream(values)
.map(value -> "\"" + escape(value) + "\"")
.collect(Collectors.joining(","));
appendFieldUnescaped(key, "[" + escapedValues + "]");
return this;
}
/**
* Appends an integer array to the JSON.
*
* @param key The key of the field.
* @param values The integer array.
* @return A reference to this object.
*/
public JsonObjectBuilder appendField(String key, int[] values) {
if (values == null) {
throw new IllegalArgumentException("JSON values must not be null");
}
String escapedValues =
Arrays.stream(values).mapToObj(String::valueOf).collect(Collectors.joining(","));
appendFieldUnescaped(key, "[" + escapedValues + "]");
return this;
}
/**
* Appends an object array to the JSON.
*
* @param key The key of the field.
* @param values The integer array.
* @return A reference to this object.
*/
public JsonObjectBuilder appendField(String key, JsonObject[] values) {
if (values == null) {
throw new IllegalArgumentException("JSON values must not be null");
}
String escapedValues =
Arrays.stream(values).map(JsonObject::toString).collect(Collectors.joining(","));
appendFieldUnescaped(key, "[" + escapedValues + "]");
return this;
}
/**
* Appends a field to the object.
*
* @param key The key of the field.
* @param escapedValue The escaped value of the field.
*/
private void appendFieldUnescaped(String key, String escapedValue) {
if (builder == null) {
throw new IllegalStateException("JSON has already been built");
}
if (key == null) {
throw new IllegalArgumentException("JSON key must not be null");
}
if (hasAtLeastOneField) {
builder.append(",");
}
builder.append("\"").append(escape(key)).append("\":").append(escapedValue);
hasAtLeastOneField = true;
}
/**
* Builds the JSON string and invalidates this builder.
*
* @return The built JSON string.
*/
public JsonObject build() {
if (builder == null) {
throw new IllegalStateException("JSON has already been built");
}
JsonObject object = new JsonObject(builder.append("}").toString());
builder = null;
return object;
}
/**
* Escapes the given string like stated in https://www.ietf.org/rfc/rfc4627.txt.
*
* <p>This method escapes only the necessary characters '"', '\'. and '\u0000' - '\u001F'.
* Compact escapes are not used (e.g., '\n' is escaped as "\u000a" and not as "\n").
*
* @param value The value to escape.
* @return The escaped value.
*/
private static String escape(String value) {
final StringBuilder builder = new StringBuilder();
for (int i = 0; i < value.length(); i++) {
char c = value.charAt(i);
if (c == '"') {
builder.append("\\\"");
} else if (c == '\\') {
builder.append("\\\\");
} else if (c <= '\u000F') {
builder.append("\\u000").append(Integer.toHexString(c));
} else if (c <= '\u001F') {
builder.append("\\u00").append(Integer.toHexString(c));
} else {
builder.append(c);
}
}
return builder.toString();
}
/**
* A super simple representation of a JSON object.
*
* <p>This class only exists to make methods of the {@link JsonObjectBuilder} type-safe and not
* allow a raw string inputs for methods like {@link JsonObjectBuilder#appendField(String,
* JsonObject)}.
*/
public static class JsonObject {
private final String value;
private JsonObject(String value) {
this.value = value;
}
@Override
public String toString() {
return value;
}
}
}
}

View File

@ -15,7 +15,7 @@ public class ReplacementScanner extends FileScanner {
TreeMap<Integer, LinkedList<String>> order = new TreeMap<Integer, LinkedList<String>>(Comparator.reverseOrder());
for (String key : replacements.keySet()) {
int length = key.length();
if (!order.keySet().contains(length)) order.put(length, new LinkedList<>());
if (!order.containsKey(length)) order.put(length, new LinkedList<>());
order.get(length).add(key);
}

View File

@ -28,8 +28,7 @@ public class PacketAddServer implements PacketObjectIn<Integer>, PacketObjectOut
* @param plugin SubPlugin
*/
public PacketAddServer(SubProxy plugin) {
Util.nullpo(plugin);
this.plugin = plugin;
this.plugin = Util.nullpo(plugin);
}
/**
@ -62,7 +61,7 @@ public class PacketAddServer implements PacketObjectIn<Integer>, PacketObjectOut
ObjectMap<String> opt = new ObjectMap<>((Map<String, ?>)data.getObject(0x0003));
UUID player = (data.contains(0x0004)?data.getUUID(0x0004):null);
if (plugin.api.getServers().keySet().contains(name.toLowerCase())) {
if (plugin.api.getServers().containsKey(name.toLowerCase())) {
client.sendPacket(new PacketAddServer(3, tracker));
} else {
if (!subserver) {
@ -72,7 +71,7 @@ public class PacketAddServer implements PacketObjectIn<Integer>, PacketObjectOut
} else {
client.sendPacket(new PacketAddServer(1, tracker));
}
} else if (!plugin.api.getHosts().keySet().contains(opt.getString("host").toLowerCase())) {
} else if (!plugin.api.getHosts().containsKey(opt.getString("host").toLowerCase())) {
client.sendPacket(new PacketAddServer(4, tracker));
} else {
if (plugin.api.getHost(opt.getString("host")).addSubServer(player, name, opt.getBoolean("enabled"), opt.getInt("port"), ChatColor.translateAlternateColorCodes('&', Util.unescapeJavaString(opt.getString("motd"))),

View File

@ -48,7 +48,6 @@ public class PacketCheckPermissionResponse implements PacketObjectIn<Integer>, P
@Override
public void receive(SubDataClient client, ObjectMap<Integer> data) throws Throwable {
for (Consumer<Boolean> callback : callbacks.get(data.getUUID(0x0000))) callback.accept(data.getBoolean(0x0001));
callbacks.remove(data.getUUID(0x0000));
for (Consumer<Boolean> callback : callbacks.remove(data.getUUID(0x0000))) callback.accept(data.getBoolean(0x0001));
}
}

View File

@ -26,8 +26,7 @@ public class PacketCommandServer implements PacketObjectIn<Integer>, PacketObjec
* @param plugin SubPlugin
*/
public PacketCommandServer(SubProxy plugin) {
Util.nullpo(plugin);
this.plugin = plugin;
this.plugin = Util.nullpo(plugin);
}
/**
@ -59,7 +58,7 @@ public class PacketCommandServer implements PacketObjectIn<Integer>, PacketObjec
UUID target = (data.contains(0x0004)?data.getUUID(0x0004):null);
Map<String, Server> servers = plugin.api.getServers();
if (!server.equals("*") && !servers.keySet().contains(server.toLowerCase())) {
if (!server.equals("*") && !servers.containsKey(server.toLowerCase())) {
client.sendPacket(new PacketCommandServer(3, tracker));
} else if (!server.equals("*") && !(target == null && servers.get(server.toLowerCase()) instanceof SubServer) && servers.get(server.toLowerCase()).getSubData()[0] == null) {
client.sendPacket(new PacketCommandServer(4, tracker));

View File

@ -60,15 +60,15 @@ public class PacketCreateServer implements PacketObjectIn<Integer>, PacketObject
if (name.contains(" ")) {
client.sendPacket(new PacketCreateServer(3, tracker));
} else if (plugin.api.getSubServers().keySet().contains(name.toLowerCase()) || SubCreator.isReserved(name)) {
} else if (plugin.api.getSubServers().containsKey(name.toLowerCase()) || SubCreator.isReserved(name)) {
client.sendPacket(new PacketCreateServer(4, tracker));
} else if (!plugin.hosts.keySet().contains(host.toLowerCase())) {
} else if (!plugin.hosts.containsKey(host.toLowerCase())) {
client.sendPacket(new PacketCreateServer(5, tracker));
} else if (!plugin.hosts.get(host.toLowerCase()).isAvailable()) {
client.sendPacket(new PacketCreateServer(6, tracker));
} else if (!plugin.hosts.get(host.toLowerCase()).isEnabled()) {
client.sendPacket(new PacketCreateServer(7, tracker));
} else if (!plugin.hosts.get(host.toLowerCase()).getCreator().getTemplates().keySet().contains(template.toLowerCase())) {
} else if (!plugin.hosts.get(host.toLowerCase()).getCreator().getTemplates().containsKey(template.toLowerCase())) {
client.sendPacket(new PacketCreateServer(8, tracker));
} else if (!plugin.hosts.get(host.toLowerCase()).getCreator().getTemplate(template).isEnabled()) {
client.sendPacket(new PacketCreateServer(9, tracker));

View File

@ -26,8 +26,7 @@ public class PacketDeleteServer implements PacketObjectIn<Integer>, PacketObject
* @param plugin SubPlugin
*/
public PacketDeleteServer(SubProxy plugin) {
Util.nullpo(plugin);
this.plugin = plugin;
this.plugin = Util.nullpo(plugin);
}
/**
@ -59,7 +58,7 @@ public class PacketDeleteServer implements PacketObjectIn<Integer>, PacketObject
UUID player = (data.contains(0x0004)?data.getUUID(0x0004):null);
Map<String, Server> servers = plugin.api.getServers();
if (!servers.keySet().contains(name.toLowerCase())) {
if (!servers.containsKey(name.toLowerCase())) {
client.sendPacket(new PacketDeleteServer(3, tracker));
} else if (!(servers.get(name.toLowerCase()) instanceof SubServer)) {
client.sendPacket(new PacketDeleteServer(4, tracker));

View File

@ -1,8 +1,8 @@
package net.ME1312.SubServers.Bungee.Network.Packet;
import net.ME1312.Galaxi.Library.AsyncConsolidator;
import net.ME1312.Galaxi.Library.Container.Container;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.Galaxi.Library.Merger;
import net.ME1312.SubData.Server.Protocol.PacketObjectIn;
import net.ME1312.SubData.Server.Protocol.PacketObjectOut;
import net.ME1312.SubData.Server.SubDataClient;
@ -82,7 +82,7 @@ public class PacketDisconnectPlayer implements PacketObjectIn<Integer>, PacketOb
if (requests.size() == 0) {
callback.accept(failures.value);
} else {
AsyncConsolidator merge = new AsyncConsolidator(() -> {
Merger merge = new Merger(() -> {
callback.accept(failures.value);
});
for (Map.Entry<Proxy, List<UUID>> entry : requests.entrySet()) {

View File

@ -24,8 +24,7 @@ public class PacketDownloadGroupInfo implements PacketObjectIn<Integer>, PacketO
* @param plugin SubPlugin
*/
public PacketDownloadGroupInfo(SubProxy plugin) {
Util.nullpo(plugin);
this.plugin = plugin;
this.plugin = Util.nullpo(plugin);
}
/**
@ -36,8 +35,7 @@ public class PacketDownloadGroupInfo implements PacketObjectIn<Integer>, PacketO
* @param tracker Receiver ID
*/
public PacketDownloadGroupInfo(SubProxy plugin, List<String> groups, UUID tracker) {
Util.nullpo(plugin);
this.plugin = plugin;
this.plugin = Util.nullpo(plugin);
this.tracker = tracker;
if (groups != null) {

View File

@ -26,8 +26,7 @@ public class PacketDownloadHostInfo implements PacketObjectIn<Integer>, PacketOb
* @param plugin SubPlugin
*/
public PacketDownloadHostInfo(SubProxy plugin) {
Util.nullpo(plugin);
this.plugin = plugin;
this.plugin = Util.nullpo(plugin);
}
/**
@ -38,8 +37,7 @@ public class PacketDownloadHostInfo implements PacketObjectIn<Integer>, PacketOb
* @param tracker Receiver ID
*/
public PacketDownloadHostInfo(SubProxy plugin, List<String> hosts, UUID tracker) {
Util.nullpo(plugin);
this.plugin = plugin;
this.plugin = Util.nullpo(plugin);
this.tracker = tracker;
if (hosts != null) {

View File

@ -26,8 +26,7 @@ public class PacketDownloadPlayerInfo implements PacketObjectIn<Integer>, Packet
* @param plugin SubPlugin
*/
public PacketDownloadPlayerInfo(SubProxy plugin) {
Util.nullpo(plugin);
this.plugin = plugin;
this.plugin = Util.nullpo(plugin);
}
/**
@ -39,8 +38,7 @@ public class PacketDownloadPlayerInfo implements PacketObjectIn<Integer>, Packet
* @param tracker Receiver ID
*/
public PacketDownloadPlayerInfo(SubProxy plugin, List<String> names, List<UUID> ids, UUID tracker) {
Util.nullpo(plugin);
this.plugin = plugin;
this.plugin = Util.nullpo(plugin);
this.tracker = tracker;
if (ids != null) {

View File

@ -26,8 +26,7 @@ public class PacketDownloadProxyInfo implements PacketObjectIn<Integer>, PacketO
* @param plugin SubPlugin
*/
public PacketDownloadProxyInfo(SubProxy plugin) {
Util.nullpo(plugin);
this.plugin = plugin;
this.plugin = Util.nullpo(plugin);
}
/**
@ -38,8 +37,7 @@ public class PacketDownloadProxyInfo implements PacketObjectIn<Integer>, PacketO
* @param tracker Receiver ID
*/
public PacketDownloadProxyInfo(SubProxy plugin, List<String> proxies, UUID tracker) {
Util.nullpo(plugin);
this.plugin = plugin;
this.plugin = Util.nullpo(plugin);
this.tracker = tracker;
if (proxies != null) {

View File

@ -26,8 +26,7 @@ public class PacketDownloadServerInfo implements PacketObjectIn<Integer>, Packet
* @param plugin SubPlugin
*/
public PacketDownloadServerInfo(SubProxy plugin) {
Util.nullpo(plugin);
this.plugin = plugin;
this.plugin = Util.nullpo(plugin);
}
/**
@ -38,8 +37,7 @@ public class PacketDownloadServerInfo implements PacketObjectIn<Integer>, Packet
* @param tracker Receiver ID
*/
public PacketDownloadServerInfo(SubProxy plugin, List<String> servers, UUID tracker) {
Util.nullpo(plugin);
this.plugin = plugin;
this.plugin = Util.nullpo(plugin);
this.tracker = tracker;
if (servers != null) {

View File

@ -27,8 +27,7 @@ public class PacketEditServer implements PacketObjectIn<Integer>, PacketObjectOu
* @param plugin SubPlugin
*/
public PacketEditServer(SubProxy plugin) {
Util.nullpo(plugin);
this.plugin = plugin;
this.plugin = Util.nullpo(plugin);
}
/**
@ -74,7 +73,7 @@ public class PacketEditServer implements PacketObjectIn<Integer>, PacketObjectOu
UUID player = (data.contains(0x0004)?data.getUUID(0x0004):null);
Map<String, Server> servers = plugin.api.getServers();
if (!servers.keySet().contains(name.toLowerCase())) {
if (!servers.containsKey(name.toLowerCase())) {
client.sendPacket(new PacketEditServer(3, tracker));
} else if (!(servers.get(name.toLowerCase()) instanceof SubServer)) {
client.sendPacket(new PacketEditServer(4, tracker));

View File

@ -49,6 +49,10 @@ public class PacketExAddServer implements PacketObjectIn<Integer>, PacketObjectO
callbacks.put(tracker, callback);
}
public String peek() {
return name;
}
@Override
public ObjectMap<Integer> send(SubDataClient client) {
ObjectMap<Integer> data = new ObjectMap<Integer>();
@ -66,7 +70,6 @@ public class PacketExAddServer implements PacketObjectIn<Integer>, PacketObjectO
@Override
public void receive(SubDataClient client, ObjectMap<Integer> data) {
for (Consumer<ObjectMap<Integer>> callback : callbacks.get(data.getUUID(0x0000))) callback.accept(data);
callbacks.remove(data.getUUID(0x0000));
for (Consumer<ObjectMap<Integer>> callback : callbacks.remove(data.getUUID(0x0000))) callback.accept(data);
}
}

View File

@ -51,7 +51,6 @@ public class PacketExControlPlayer implements PacketObjectIn<Integer>, PacketObj
@Override
public void receive(SubDataClient client, ObjectMap<Integer> data) {
for (Consumer<ObjectMap<Integer>> callback : callbacks.get(data.getUUID(0x0000))) callback.accept(data);
callbacks.remove(data.getUUID(0x0000));
for (Consumer<ObjectMap<Integer>> callback : callbacks.remove(data.getUUID(0x0000))) callback.accept(data);
}
}

View File

@ -72,7 +72,7 @@ public class PacketExControlServer implements PacketObjectIn<Integer>, PacketObj
this.args = new Object[type.getArguments().length];
for (int i = 0; i < type.getArguments().length; ++i) {
if (!type.getArguments()[i].isInstance(arguments[i])) throw new IllegalArgumentException("Argument " + (i+1) + " is not " + type.getArguments()[i].getCanonicalName());
if (!type.getArguments()[i].isInstance(arguments[i])) throw new IllegalArgumentException("Argument " + (i+1) + " is not " + type.getArguments()[i].getTypeName());
args[i] = arguments[i];
}
}

View File

@ -117,7 +117,6 @@ public class PacketExCreateServer implements PacketObjectIn<Integer>, PacketObje
@Override
public void receive(SubDataClient client, ObjectMap<Integer> data) {
for (Consumer<ObjectMap<Integer>> callback : callbacks.get(data.getUUID(0x0000))) callback.accept(data);
callbacks.remove(data.getUUID(0x0000));
for (Consumer<ObjectMap<Integer>> callback : callbacks.remove(data.getUUID(0x0000))) callback.accept(data);
}
}

View File

@ -54,7 +54,6 @@ public class PacketExDeleteServer implements PacketObjectIn<Integer>, PacketObje
@Override
public void receive(SubDataClient client, ObjectMap<Integer> data) {
for (Consumer<ObjectMap<Integer>> callback : callbacks.get(data.getUUID(0x0000))) callback.accept(data);
callbacks.remove(data.getUUID(0x0000));
for (Consumer<ObjectMap<Integer>> callback : callbacks.remove(data.getUUID(0x0000))) callback.accept(data);
}
}

View File

@ -52,7 +52,6 @@ public class PacketExDisconnectPlayer implements PacketObjectIn<Integer>, Packet
@Override
public void receive(SubDataClient client, ObjectMap<Integer> data) {
for (Consumer<ObjectMap<Integer>> callback : callbacks.get(data.getUUID(0x0000))) callback.accept(data);
callbacks.remove(data.getUUID(0x0000));
for (Consumer<ObjectMap<Integer>> callback : callbacks.remove(data.getUUID(0x0000))) callback.accept(data);
}
}

View File

@ -54,7 +54,6 @@ public class PacketExMessagePlayer implements PacketObjectIn<Integer>, PacketObj
@Override
public void receive(SubDataClient client, ObjectMap<Integer> data) {
for (Consumer<ObjectMap<Integer>> callback : callbacks.get(data.getUUID(0x0000))) callback.accept(data);
callbacks.remove(data.getUUID(0x0000));
for (Consumer<ObjectMap<Integer>> callback : callbacks.remove(data.getUUID(0x0000))) callback.accept(data);
}
}

View File

@ -47,7 +47,6 @@ public class PacketExRemoveServer implements PacketObjectIn<Integer>, PacketObje
@Override
public void receive(SubDataClient client, ObjectMap<Integer> data) {
for (Consumer<ObjectMap<Integer>> callback : callbacks.get(data.getUUID(0x0000))) callback.accept(data);
callbacks.remove(data.getUUID(0x0000));
for (Consumer<ObjectMap<Integer>> callback : callbacks.remove(data.getUUID(0x0000))) callback.accept(data);
}
}

View File

@ -32,8 +32,7 @@ public class PacketExSyncPlayer implements PacketObjectIn<Integer>, PacketObject
* @param plugin SubPlugin
*/
public PacketExSyncPlayer(SubProxy plugin) {
Util.nullpo(plugin);
this.plugin = plugin;
this.plugin = Util.nullpo(plugin);
}
/**

View File

@ -52,7 +52,6 @@ public class PacketExTransferPlayer implements PacketObjectIn<Integer>, PacketOb
@Override
public void receive(SubDataClient client, ObjectMap<Integer> data) {
for (Consumer<ObjectMap<Integer>> callback : callbacks.get(data.getUUID(0x0000))) callback.accept(data);
callbacks.remove(data.getUUID(0x0000));
for (Consumer<ObjectMap<Integer>> callback : callbacks.remove(data.getUUID(0x0000))) callback.accept(data);
}
}

View File

@ -31,8 +31,7 @@ public class PacketLinkExHost implements InitialPacket, PacketObjectIn<Integer>,
* @param plugin SubPlugin
*/
public PacketLinkExHost(SubProxy plugin) {
Util.nullpo(plugin);
this.plugin = plugin;
this.plugin = Util.nullpo(plugin);
}
/**
@ -59,21 +58,21 @@ public class PacketLinkExHost implements InitialPacket, PacketObjectIn<Integer>,
public void receive(SubDataClient client, ObjectMap<Integer> data) {
try {
Map<String, Host> hosts = plugin.api.getHosts();
if (hosts.keySet().contains(data.getString(0x0000).toLowerCase())) {
if (hosts.containsKey(data.getString(0x0000).toLowerCase())) {
Host host = hosts.get(data.getString(0x0000).toLowerCase());
if (host instanceof ExternalHost) {
Integer channel = data.getInt(0x0001);
HashMap<Integer, SubDataClient> subdata = Try.all.get(() -> Util.reflect(ExternalHost.class.getDeclaredField("subdata"), host));
if (!subdata.keySet().contains(channel) || (channel == 0 && subdata.get(0) == null)) {
if (!subdata.containsKey(channel) || (channel == 0 && subdata.get(0) == null)) {
((ExternalHost) host).setSubData(client, channel);
Logger.get("SubData").info(client.getAddress().toString() + " has been defined as Host: " + host.getName() + ((channel > 0)?" [+"+channel+"]":""));
queue(host.getName(), () -> client.sendPacket(new PacketLinkExHost(0, null)));
setReady(client);
} else {
client.sendPacket(new PacketLinkExHost(3, "Host already linked"));
client.sendPacket(new PacketLinkExHost(3, "Host already linked: " + data.getString(0x0000)));
}
} else {
client.sendPacket(new PacketLinkExHost(4, "That host does not support a network interface"));
client.sendPacket(new PacketLinkExHost(4, "Requested host does not support network interfaces: " + data.getString(0x0000)));
}
} else {
client.sendPacket(new PacketLinkExHost(2, "There is no host with name: " + data.getString(0x0000)));

View File

@ -32,8 +32,7 @@ public class PacketLinkProxy implements InitialPacket, PacketObjectIn<Integer>,
* @param plugin SubPlugin
*/
public PacketLinkProxy(SubProxy plugin) {
Util.nullpo(plugin);
this.plugin = plugin;
this.plugin = Util.nullpo(plugin);
}
/**
@ -66,22 +65,22 @@ public class PacketLinkProxy implements InitialPacket, PacketObjectIn<Integer>,
boolean isnew = false;
Proxy proxy;
if (name != null && proxies.keySet().contains(name.toLowerCase())) {
if (name != null && proxies.containsKey(name.toLowerCase())) {
proxy = proxies.get(name.toLowerCase());
} else {
proxy = new Proxy((name != null && !proxies.keySet().contains(name.toLowerCase()))?name:null);
proxy = new Proxy((name != null && !proxies.containsKey(name.toLowerCase()))?name:null);
isnew = true;
plugin.proxies.put(proxy.getName().toLowerCase(), proxy);
}
HashMap<Integer, SubDataClient> subdata = Try.all.get(() -> Util.reflect(Proxy.class.getDeclaredField("subdata"), proxy));
if (!subdata.keySet().contains(channel) || (channel == 0 && subdata.get(0) == null)) {
if (!subdata.containsKey(channel) || (channel == 0 && subdata.get(0) == null)) {
proxy.setSubData(client, channel);
if (isnew) plugin.getPluginManager().callEvent(new SubAddProxyEvent(proxy));
Logger.get("SubData").info(client.getAddress().toString() + " has been defined as Proxy: " + proxy.getName() + ((channel > 0)?" [+"+channel+"]":""));
queue(proxy.getName(), () -> client.sendPacket(new PacketLinkProxy(proxy.getName(), 0, null)));
setReady(client);
} else {
client.sendPacket(new PacketLinkProxy(proxy.getName(), 2, "Proxy already linked"));
client.sendPacket(new PacketLinkProxy(null, 2, "Proxy already linked: " + proxy.getName()));
}
} catch (Throwable e) {

View File

@ -45,8 +45,7 @@ public class PacketLinkServer implements InitialPacket, PacketObjectIn<Integer>,
* @param plugin SubPlugin
*/
public PacketLinkServer(SubProxy plugin) {
Util.nullpo(plugin);
this.plugin = plugin;
this.plugin = Util.nullpo(plugin);
}
/**
@ -90,7 +89,7 @@ public class PacketLinkServer implements InitialPacket, PacketObjectIn<Integer>,
Server server;
Map<String, Server> servers = plugin.api.getServers();
if (name != null && servers.keySet().contains(name.toLowerCase())) {
if (name != null && servers.containsKey(name.toLowerCase())) {
link(client, servers.get(name.toLowerCase()), channel);
} else if (address != null) {
if ((server = search(address)) != null || (server = create(name, address)) != null) {
@ -139,12 +138,12 @@ public class PacketLinkServer implements InitialPacket, PacketObjectIn<Integer>,
static long last = Calendar.getInstance().getTime().getTime();
private void link(SubDataClient client, Server server, int channel) throws Throwable {
HashMap<Integer, SubDataClient> subdata = Try.all.get(() -> Util.reflect(ServerImpl.class.getDeclaredField("subdata"), server));
if (!subdata.keySet().contains(channel) || (channel == 0 && subdata.get(0) == null)) {
if (!subdata.containsKey(channel) || (channel == 0 && subdata.get(0) == null)) {
server.setSubData(client, channel);
Logger.get("SubData").info(client.getAddress().toString() + " has been defined as " + ((server instanceof SubServer) ? "SubServer" : "Server") + ": " + server.getName() + ((channel > 0)?" [+"+channel+"]":""));
Runnable register = () -> {
if (server instanceof SubServer && !((SubServer) server).isRunning()) {
if (((SubServer) server).getHost().isAvailable()) {
if (((SubServer) server).isAvailable()) {
Logger.get("SubServers").info("Sending shutdown signal to rogue SubServer: " + server.getName());
client.sendPacket(new PacketOutExReset("Rogue SubServer Detected"));
} else {
@ -176,7 +175,7 @@ public class PacketLinkServer implements InitialPacket, PacketObjectIn<Integer>,
last = now;
setReady(client);
} else {
client.sendPacket(new PacketLinkServer(null, 4, "Server already linked"));
client.sendPacket(new PacketLinkServer(null, 4, "Server already linked: " + server.getName()));
}
}
}

View File

@ -1,9 +1,9 @@
package net.ME1312.SubServers.Bungee.Network.Packet;
import net.ME1312.Galaxi.Library.AsyncConsolidator;
import net.ME1312.Galaxi.Library.Container.ContainedPair;
import net.ME1312.Galaxi.Library.Container.Container;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.Galaxi.Library.Merger;
import net.ME1312.SubData.Server.Protocol.PacketObjectIn;
import net.ME1312.SubData.Server.Protocol.PacketObjectOut;
import net.ME1312.SubData.Server.SubDataClient;
@ -101,7 +101,7 @@ public class PacketMessagePlayer implements PacketObjectIn<Integer>, PacketObjec
if (requests.size() == 0) {
callback.accept(failures.value);
} else {
AsyncConsolidator merge = new AsyncConsolidator(() -> {
Merger merge = new Merger(() -> {
callback.accept(failures.value);
});
List<String> legacy, raw;

View File

@ -74,7 +74,7 @@ public class PacketOutExEditServer implements PacketObjectOut<Integer> {
this.args = new Object[type.getArguments().length];
for (int i = 0; i < type.getArguments().length; ++i) {
if (!type.getArguments()[i].isInstance(arguments[i])) throw new IllegalArgumentException("Argument " + (i+1) + " is not " + type.getArguments()[i].getCanonicalName());
if (!type.getArguments()[i].isInstance(arguments[i])) throw new IllegalArgumentException("Argument " + (i+1) + " is not " + type.getArguments()[i].getTypeName());
args[i] = arguments[i];
}
}

View File

@ -28,8 +28,7 @@ public class PacketOutExRunEvent implements Listener, PacketObjectOut<Integer> {
* @param plugin
*/
public PacketOutExRunEvent(SubProxy plugin) {
Util.nullpo(plugin);
this.plugin = plugin;
this.plugin = Util.nullpo(plugin);
}
/**

View File

@ -27,8 +27,7 @@ public class PacketRemoveServer implements PacketObjectIn<Integer>, PacketObject
* @param plugin SubPlugin
*/
public PacketRemoveServer(SubProxy plugin) {
Util.nullpo(plugin);
this.plugin = plugin;
this.plugin = Util.nullpo(plugin);
}
/**
@ -59,7 +58,7 @@ public class PacketRemoveServer implements PacketObjectIn<Integer>, PacketObject
UUID player = (data.contains(0x0003)?data.getUUID(0x0003):null);
Map<String, Server> servers = plugin.api.getServers();
if (!servers.keySet().contains(name.toLowerCase())) {
if (!servers.containsKey(name.toLowerCase())) {
client.sendPacket(new PacketRemoveServer(3, tracker));
} else if (!(servers.get(name.toLowerCase()) instanceof SubServer)) {
if (force) {

View File

@ -26,8 +26,7 @@ public class PacketRestartServer implements PacketObjectIn<Integer>, PacketObjec
* @param plugin SubPlugin
*/
public PacketRestartServer(SubProxy plugin) {
Util.nullpo(plugin);
this.plugin = plugin;
this.plugin = Util.nullpo(plugin);
}
/**
@ -58,7 +57,7 @@ public class PacketRestartServer implements PacketObjectIn<Integer>, PacketObjec
Runnable starter = () -> {
Map<String, Server> servers = plugin.api.getServers();
if (!servers.keySet().contains(name.toLowerCase())) {
if (!servers.containsKey(name.toLowerCase())) {
} else if (!(servers.get(name.toLowerCase()) instanceof SubServer)) {
} else if (!((SubServer) servers.get(name.toLowerCase())).getHost().isAvailable()) {
} else if (!((SubServer) servers.get(name.toLowerCase())).getHost().isEnabled()) {
@ -72,7 +71,7 @@ public class PacketRestartServer implements PacketObjectIn<Integer>, PacketObjec
};
Map<String, Server> servers = plugin.api.getServers();
if (!servers.keySet().contains(name.toLowerCase())) {
if (!servers.containsKey(name.toLowerCase())) {
client.sendPacket(new PacketRestartServer(3, tracker));
} else if (!(servers.get(name.toLowerCase()) instanceof SubServer)) {
client.sendPacket(new PacketRestartServer(4, tracker));

View File

@ -27,8 +27,7 @@ public class PacketStartServer implements PacketObjectIn<Integer>, PacketObjectO
* @param plugin SubPlugin
*/
public PacketStartServer(SubProxy plugin) {
Util.nullpo(plugin);
this.plugin = plugin;
this.plugin = Util.nullpo(plugin);
}
/**
@ -70,7 +69,7 @@ public class PacketStartServer implements PacketObjectIn<Integer>, PacketObjectO
UUID player = (data.contains(0x0002)?data.getUUID(0x0002):null);
Map<String, Server> servers = plugin.api.getServers();
if (!servers.keySet().contains(name.toLowerCase())) {
if (!servers.containsKey(name.toLowerCase())) {
client.sendPacket(new PacketStartServer(3, tracker));
} else if (!(servers.get(name.toLowerCase()) instanceof SubServer)) {
client.sendPacket(new PacketStartServer(4, tracker));

View File

@ -26,8 +26,7 @@ public class PacketStopServer implements PacketObjectIn<Integer>, PacketObjectOu
* @param plugin SubPlugin
*/
public PacketStopServer(SubProxy plugin) {
Util.nullpo(plugin);
this.plugin = plugin;
this.plugin = Util.nullpo(plugin);
}
/**
@ -58,7 +57,7 @@ public class PacketStopServer implements PacketObjectIn<Integer>, PacketObjectOu
UUID player = (data.contains(0x0003)?data.getUUID(0x0003):null);
Map<String, Server> servers = plugin.api.getServers();
if (!name.equals("*") && !servers.keySet().contains(name.toLowerCase())) {
if (!name.equals("*") && !servers.containsKey(name.toLowerCase())) {
client.sendPacket(new PacketStopServer(3, tracker));
} else if (!name.equals("*") && !(servers.get(name.toLowerCase()) instanceof SubServer)) {
client.sendPacket(new PacketStopServer(4, tracker));

View File

@ -1,8 +1,8 @@
package net.ME1312.SubServers.Bungee.Network.Packet;
import net.ME1312.Galaxi.Library.AsyncConsolidator;
import net.ME1312.Galaxi.Library.Container.Container;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.Galaxi.Library.Merger;
import net.ME1312.SubData.Server.Protocol.PacketObjectIn;
import net.ME1312.SubData.Server.Protocol.PacketObjectOut;
import net.ME1312.SubData.Server.SubDataClient;
@ -83,7 +83,7 @@ public class PacketTransferPlayer implements PacketObjectIn<Integer>, PacketObje
if (requests.size() == 0) {
callback.accept(failures.value);
} else {
AsyncConsolidator merge = new AsyncConsolidator(() -> {
Merger merge = new Merger(() -> {
callback.accept(failures.value);
});
for (Map.Entry<Proxy, List<UUID>> entry : requests.entrySet()) {

View File

@ -60,7 +60,7 @@ public class PacketUpdateServer implements PacketObjectIn<Integer>, PacketObject
boolean waitfor = (data.contains(0x0005)?data.getBoolean(0x0005):false);
Map<String, Server> servers = plugin.api.getServers();
if (!servers.keySet().contains(name.toLowerCase())) {
if (!servers.containsKey(name.toLowerCase())) {
client.sendPacket(new PacketUpdateServer(3, tracker));
} else if (!(servers.get(name.toLowerCase()) instanceof SubServer)) {
client.sendPacket(new PacketUpdateServer(4, tracker));

View File

@ -95,7 +95,7 @@ public final class SubAPI implements BungeeAPI {
*/
public void addHostDriver(Class<? extends Host> driver, String handle) {
Util.nullpo(driver, handle);
if (plugin.hostDrivers.keySet().contains(handle.toUpperCase().replace('-', '_').replace(' ', '_'))) throw new IllegalStateException("Driver already exists: " + handle);
if (plugin.hostDrivers.containsKey(handle.toUpperCase().replace('-', '_').replace(' ', '_'))) throw new IllegalStateException("Driver already exists: " + handle);
plugin.hostDrivers.put(handle.toUpperCase().replace('-', '_').replace(' ', '_'), driver);
}
@ -317,12 +317,12 @@ public final class SubAPI implements BungeeAPI {
for (Server server : getServers().values()) {
for (String name : server.getGroups()) {
String group = name;
if (conflitresolver.keySet().contains(name.toLowerCase())) {
if (conflitresolver.containsKey(name.toLowerCase())) {
group = conflitresolver.get(name.toLowerCase());
} else {
conflitresolver.put(name.toLowerCase(), name);
}
List<Server> list = (groups.keySet().contains(group))?groups.get(group):new LinkedList<Server>();
List<Server> list = (groups.containsKey(group))?groups.get(group):new LinkedList<Server>();
list.add(server);
groups.put(group, list);
}
@ -435,7 +435,7 @@ public final class SubAPI implements BungeeAPI {
* @return Success status
*/
public boolean addServer(UUID player, Server server) {
if (getServers().keySet().contains(server.getName().toLowerCase())) throw new InvalidServerException("A Server already exists with this name!");
if (getServers().containsKey(server.getName().toLowerCase())) throw new InvalidServerException("A Server already exists with this name!");
SubAddServerEvent event = new SubAddServerEvent(player, null, server);
plugin.getPluginManager().callEvent(event);
if (!event.isCancelled()) {
@ -586,7 +586,7 @@ public final class SubAPI implements BungeeAPI {
players.put(id, plugin.rPlayers.get(id));
return players;
} else {
return new HashMap<>();
return Collections.emptyMap();
}
}

View File

@ -30,6 +30,7 @@ import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
@ -289,7 +290,10 @@ public final class SubCommand extends Command implements TabExecutor {
sender.sendMessage(" -> Players: " + ChatColor.AQUA + server.getRemotePlayers().size() + " online");
}
sender.sendMessage(" -> MOTD: " + ChatColor.WHITE + ChatColor.stripColor(server.getMotd()));
if (server instanceof SubServer && ((SubServer) server).getStopAction() != SubServer.StopAction.NONE) sender.sendMessage(" -> Stop Action: " + ChatColor.WHITE + ((SubServer) server).getStopAction().toString());
if (server instanceof SubServer) {
if (((SubServer) server).getStopAction() != SubServer.StopAction.NONE) sender.sendMessage(" -> Stop Action: " + ChatColor.WHITE + ((SubServer) server).getStopAction().toString());
if (((SubServer) server).isStopping()) sender.sendMessage(" -> Stopping: " + ChatColor.GREEN+"yes");
}
sender.sendMessage(" -> Signature: " + ChatColor.AQUA + server.getSignature());
if (server instanceof SubServer) sender.sendMessage(" -> Logging: " + ((((SubServer) server).isLogging())?ChatColor.GREEN+"yes":ChatColor.RED+"no"));
sender.sendMessage(" -> Restricted: " + ((server.isRestricted())?ChatColor.GREEN+"yes":ChatColor.RED+"no"));
@ -435,7 +439,7 @@ public final class SubCommand extends Command implements TabExecutor {
if (select.subservers.length > 0) {
Consumer<SubServer> starter = server -> {
Map<String, Server> servers = plugin.api.getServers();
if (!servers.keySet().contains(server.getName().toLowerCase()) || !(servers.get(server.getName().toLowerCase()) instanceof SubServer)) {
if (!servers.containsKey(server.getName().toLowerCase()) || !(servers.get(server.getName().toLowerCase()) instanceof SubServer)) {
sender.sendMessage("SubServers > Could not restart server: Subserver " + server.getName() + " has disappeared");
} else if (!(server = (SubServer) servers.get(server.getName().toLowerCase())).isRunning()) {
if (!server.getHost().isAvailable()) {
@ -562,7 +566,7 @@ public final class SubCommand extends Command implements TabExecutor {
if (plugin.canSudo) {
if (args.length > 1) {
Map<String, Server> servers = plugin.api.getServers();
if (!servers.keySet().contains(args[1].toLowerCase()) || !(servers.get(args[1].toLowerCase()) instanceof SubServer)) {
if (!servers.containsKey(args[1].toLowerCase()) || !(servers.get(args[1].toLowerCase()) instanceof SubServer)) {
sender.sendMessage("SubServers > There is no subserver with that name");
} else if (!((SubServer) servers.get(args[1].toLowerCase())).isRunning()) {
sender.sendMessage("SubServers > That subserver is not running");
@ -578,15 +582,15 @@ public final class SubCommand extends Command implements TabExecutor {
}
} else if (args[0].equalsIgnoreCase("create")) {
if (args.length > 3) {
if (plugin.api.getSubServers().keySet().contains(args[1].toLowerCase()) || SubCreator.isReserved(args[1])) {
if (plugin.api.getSubServers().containsKey(args[1].toLowerCase()) || SubCreator.isReserved(args[1])) {
sender.sendMessage("SubServers > There is already a subserver with that name");
} else if (!plugin.hosts.keySet().contains(args[2].toLowerCase())) {
} else if (!plugin.hosts.containsKey(args[2].toLowerCase())) {
sender.sendMessage("SubServers > There is no host with that name");
} else if (!plugin.hosts.get(args[2].toLowerCase()).isAvailable()) {
sender.sendMessage("SubServers > That host is not available");
} else if (!plugin.hosts.get(args[2].toLowerCase()).isEnabled()) {
sender.sendMessage("SubServers > That host is not enabled");
} else if (!plugin.hosts.get(args[2].toLowerCase()).getCreator().getTemplates().keySet().contains(args[3].toLowerCase())) {
} else if (!plugin.hosts.get(args[2].toLowerCase()).getCreator().getTemplates().containsKey(args[3].toLowerCase())) {
sender.sendMessage("SubServers > There is no template with that name");
} else if (!plugin.hosts.get(args[2].toLowerCase()).getCreator().getTemplate(args[3].toLowerCase()).isEnabled()) {
sender.sendMessage("SubServers > That template is not enabled");
@ -668,9 +672,12 @@ public final class SubCommand extends Command implements TabExecutor {
sender.sendMessages(printHelp());
}
} else {
String str = label;
for (String arg : args) str += ' ' + arg;
((ProxiedPlayer) sender).chat(str);
ProxiedPlayer player = (ProxiedPlayer) sender;
if (player.getPendingConnection().getVersion() < 759) { // player < 1.19
player.chat((args.length == 0)? label : label + ' ' + String.join(" ", args));
} else {
player.getServer().sendData("subservers:input", ((args.length == 0)? label : label + ' ' + String.join(" ", args)).getBytes(StandardCharsets.UTF_8));
}
}
}
@ -854,19 +861,19 @@ public final class SubCommand extends Command implements TabExecutor {
String Last = (args.length > 0)?args[args.length - 1]:"";
String last = Last.toLowerCase();
if (sender instanceof ProxiedPlayer && (!players.keySet().contains(((ProxiedPlayer) sender).getUniqueId()) || !players.get(((ProxiedPlayer) sender).getUniqueId()).keySet().contains(((ProxiedPlayer) sender).getServer().getInfo())
if (sender instanceof ProxiedPlayer && (!players.containsKey(((ProxiedPlayer) sender).getUniqueId()) || !players.get(((ProxiedPlayer) sender).getUniqueId()).containsKey(((ProxiedPlayer) sender).getServer().getInfo())
|| !players.get(((ProxiedPlayer) sender).getUniqueId()).get(((ProxiedPlayer) sender).getServer().getInfo()).value())) {
if (players.keySet().contains(((ProxiedPlayer) sender).getUniqueId()) && players.get(((ProxiedPlayer) sender).getUniqueId()).keySet().contains(((ProxiedPlayer) sender).getServer().getInfo())
if (players.containsKey(((ProxiedPlayer) sender).getUniqueId()) && players.get(((ProxiedPlayer) sender).getUniqueId()).containsKey(((ProxiedPlayer) sender).getServer().getInfo())
&& players.get(((ProxiedPlayer) sender).getUniqueId()).get(((ProxiedPlayer) sender).getServer().getInfo()).key() == null) {
// do nothing
} else if (!players.keySet().contains(((ProxiedPlayer) sender).getUniqueId()) || !players.get(((ProxiedPlayer) sender).getUniqueId()).keySet().contains(((ProxiedPlayer) sender).getServer().getInfo())
} else if (!players.containsKey(((ProxiedPlayer) sender).getUniqueId()) || !players.get(((ProxiedPlayer) sender).getUniqueId()).containsKey(((ProxiedPlayer) sender).getServer().getInfo())
|| Calendar.getInstance().getTime().getTime() - players.get(((ProxiedPlayer) sender).getUniqueId()).get(((ProxiedPlayer) sender).getServer().getInfo()).key() >= TimeUnit.MINUTES.toMillis(1)) {
if (!(((ProxiedPlayer) sender).getServer().getInfo() instanceof Server) || ((Server) ((ProxiedPlayer) sender).getServer().getInfo()).getSubData()[0] == null) {
HashMap<ServerInfo, Pair<Long, Boolean>> map = (players.keySet().contains(((ProxiedPlayer) sender).getUniqueId()))?players.get(((ProxiedPlayer) sender).getUniqueId()):new HashMap<ServerInfo, Pair<Long, Boolean>>();
HashMap<ServerInfo, Pair<Long, Boolean>> map = (players.containsKey(((ProxiedPlayer) sender).getUniqueId()))?players.get(((ProxiedPlayer) sender).getUniqueId()):new HashMap<ServerInfo, Pair<Long, Boolean>>();
map.put(((ProxiedPlayer) sender).getServer().getInfo(), new ContainedPair<>(Calendar.getInstance().getTime().getTime(), false));
players.put(((ProxiedPlayer) sender).getUniqueId(), map);
} else {
HashMap<ServerInfo, Pair<Long, Boolean>> map = (players.keySet().contains(((ProxiedPlayer) sender).getUniqueId()))?players.get(((ProxiedPlayer) sender).getUniqueId()):new HashMap<ServerInfo, Pair<Long, Boolean>>();
HashMap<ServerInfo, Pair<Long, Boolean>> map = (players.containsKey(((ProxiedPlayer) sender).getUniqueId()))?players.get(((ProxiedPlayer) sender).getUniqueId()):new HashMap<ServerInfo, Pair<Long, Boolean>>();
map.put(((ProxiedPlayer) sender).getServer().getInfo(), new ContainedPair<>(null, false));
players.put(((ProxiedPlayer) sender).getUniqueId(), map);
((SubDataClient) ((Server) ((ProxiedPlayer) sender).getServer().getInfo()).getSubData()[0]).sendPacket(new PacketCheckPermission(((ProxiedPlayer) sender).getUniqueId(), "subservers.command", result -> {
@ -1072,7 +1079,7 @@ public final class SubCommand extends Command implements TabExecutor {
} else if (args.length == 4) {
List<String> list = new ArrayList<String>();
Map<String, Host> hosts = plugin.api.getHosts();
if (!hosts.keySet().contains(args[2].toLowerCase())) {
if (!hosts.containsKey(args[2].toLowerCase())) {
list.add("<Template>");
} else {
for (SubCreator.ServerTemplate template : hosts.get(args[2].toLowerCase()).getCreator().getTemplates().values()) {
@ -1157,7 +1164,7 @@ public final class SubCommand extends Command implements TabExecutor {
if (sender instanceof ProxiedPlayer) {
if (args.length > 0) {
Map<String, Server> servers = plugin.api.getServers();
if (servers.keySet().contains(args[0].toLowerCase())) {
if (servers.containsKey(args[0].toLowerCase())) {
((ProxiedPlayer) sender).connect(servers.get(args[0].toLowerCase()));
} else {
sender.sendMessage(plugin.api.getLang("SubServers", "Bungee.Server.Invalid"));

View File

@ -34,6 +34,7 @@ import net.ME1312.SubServers.Bungee.Network.SubProtocol;
import com.dosse.upnp.UPnP;
import com.google.common.collect.Range;
import com.google.gson.Gson;
import io.netty.channel.Channel;
import net.md_5.bungee.BungeeServerInfo;
import net.md_5.bungee.UserConnection;
import net.md_5.bungee.api.ChatColor;
@ -92,7 +93,8 @@ public final class SubProxy extends BungeeCommon implements Listener {
public SubProtocol subprotocol;
public SubDataServer subdata = null;
public SubServer sudo = null;
public static final Version version = Version.fromString("2.18a");
public final Collection<Channel> listeners = super.listeners;
public static final Version version = Version.fromString("2.20a");
public final Proxy mProxy;
public boolean canSudo = false;
@ -155,89 +157,76 @@ public final class SubProxy extends BungeeCommon implements Listener {
Logger.get("SubServers").info("Created ./SubServers/Templates/Sponge");
} else {
long stamp = Math.round(Math.random() * 100000);
Version tv1 = new Version("2.18a+");
Version tv2 = new Version("2.18a+");
Version tv = new Version("2.18a+");
if (new File(dir, "Templates/Vanilla/template.yml").exists() && ((new YAMLConfig(new File(dir, "Templates/Vanilla/template.yml"))).get().getVersion("Version", tv2)).compareTo(tv2) != 0) {
if (new File(dir, "Templates/Vanilla/template.yml").exists() && ((new YAMLConfig(new File(dir, "Templates/Vanilla/template.yml"))).get().getVersion("Version", tv)).compareTo(tv) != 0) {
Files.move(new File(dir, "Templates/Vanilla").toPath(), new File(dir, "Templates/Vanilla." + stamp + ".x").toPath());
Directories.unzip(SubProxy.class.getResourceAsStream("/net/ME1312/SubServers/Bungee/Library/Files/Templates/vanilla.zip"), new File(dir, "Templates"));
Logger.get("SubServers").info("Updated ./SubServers/Templates/Vanilla");
}
if (new File(dir, "Templates/Spigot/template.yml").exists() && ((new YAMLConfig(new File(dir, "Templates/Spigot/template.yml"))).get().getVersion("Version", tv1)).compareTo(tv1) != 0) {
if (new File(dir, "Templates/Spigot/template.yml").exists() && ((new YAMLConfig(new File(dir, "Templates/Spigot/template.yml"))).get().getVersion("Version", tv)).compareTo(tv) != 0) {
Files.move(new File(dir, "Templates/Spigot").toPath(), new File(dir, "Templates/Spigot." + stamp + ".x").toPath());
Directories.unzip(SubProxy.class.getResourceAsStream("/net/ME1312/SubServers/Bungee/Library/Files/Templates/spigot.zip"), new File(dir, "Templates"));
Logger.get("SubServers").info("Updated ./SubServers/Templates/Spigot");
}
if (new File(dir, "Templates/Purpur/template.yml").exists() && ((new YAMLConfig(new File(dir, "Templates/Purpur/template.yml"))).get().getVersion("Version", tv2)).compareTo(tv2) != 0) {
if (new File(dir, "Templates/Purpur/template.yml").exists() && ((new YAMLConfig(new File(dir, "Templates/Purpur/template.yml"))).get().getVersion("Version", tv)).compareTo(tv) != 0) {
Files.move(new File(dir, "Templates/Purpur").toPath(), new File(dir, "Templates/Purpur." + stamp + ".x").toPath());
Directories.unzip(SubProxy.class.getResourceAsStream("/net/ME1312/SubServers/Bungee/Library/Files/Templates/purpur.zip"), new File(dir, "Templates"));
Logger.get("SubServers").info("Updated ./SubServers/Templates/Purpur");
}
if (new File(dir, "Templates/Forge/template.yml").exists() && ((new YAMLConfig(new File(dir, "Templates/Forge/template.yml"))).get().getVersion("Version", tv2)).compareTo(tv2) != 0) {
if (new File(dir, "Templates/Forge/template.yml").exists() && ((new YAMLConfig(new File(dir, "Templates/Forge/template.yml"))).get().getVersion("Version", tv)).compareTo(tv) != 0) {
Files.move(new File(dir, "Templates/Forge").toPath(), new File(dir, "Templates/Forge." + stamp + ".x").toPath());
Directories.unzip(SubProxy.class.getResourceAsStream("/net/ME1312/SubServers/Bungee/Library/Files/Templates/forge.zip"), new File(dir, "Templates"));
Logger.get("SubServers").info("Updated ./SubServers/Templates/Forge");
}
if (new File(dir, "Templates/Sponge/template.yml").exists() && ((new YAMLConfig(new File(dir, "Templates/Sponge/template.yml"))).get().getVersion("Version", tv1)).compareTo(tv1) != 0) {
if (new File(dir, "Templates/Sponge/template.yml").exists() && ((new YAMLConfig(new File(dir, "Templates/Sponge/template.yml"))).get().getVersion("Version", tv)).compareTo(tv) != 0) {
Files.move(new File(dir, "Templates/Sponge").toPath(), new File(dir, "Templates/Sponge." + stamp + ".x").toPath());
Directories.unzip(SubProxy.class.getResourceAsStream("/net/ME1312/SubServers/Bungee/Library/Files/Templates/sponge.zip"), new File(dir, "Templates"));
Logger.get("SubServers").info("Updated ./SubServers/Templates/Sponge");
}
}
Runnable clean = () -> {
try {
if (new File(dir, "Recently Deleted").exists()) {
int f = new File(dir, "Recently Deleted").listFiles().length;
for (File file : new File(dir, "Recently Deleted").listFiles()) {
try {
if (file.isDirectory()) {
if (new File(dir, "Recently Deleted/" + file.getName() + "/info.json").exists()) {
FileReader reader = new FileReader(new File(dir, "Recently Deleted/" + file.getName() + "/info.json"));
YAMLSection info = new YAMLSection(new Gson().fromJson(Util.readAll(reader), Map.class));
reader.close();
if (info.contains("Timestamp")) {
if (TimeUnit.MILLISECONDS.toDays(Calendar.getInstance().getTime().getTime() - info.getLong("Timestamp")) >= 7) {
Directories.delete(file);
f--;
Logger.get("SubServers").info("Removed ./SubServers/Recently Deleted/" + file.getName());
}
} else {
Directories.delete(file);
f--;
Logger.get("SubServers").info("Removed ./SubServers/Recently Deleted/" + file.getName());
}
} else {
Directories.delete(file);
f--;
Logger.get("SubServers").info("Removed ./SubServers/Recently Deleted/" + file.getName());
}
} else {
Files.delete(file.toPath());
f--;
Logger.get("SubServers").info("Removed ./SubServers/Recently Deleted/" + file.getName());
}
} catch (Exception e) {
Logger.get("SubServers").info("Problem scanning ./SubServers/Recently Deleted/" + file.getName());
e.printStackTrace();
Files.delete(file.toPath());
}
}
if (f <= 0) {
Files.delete(new File(dir, "Recently Deleted").toPath());
}
}
} catch (Exception e) {
e.printStackTrace();
}
};
clean.run();
new Timer("SubServers.Bungee::Recycle_Cleaner").scheduleAtFixedRate(new TimerTask() {
TimerTask cleaner;
(cleaner = new TimerTask() {
@Override
public void run() {
clean.run();
try {
File recycle = new File(dir, "Recently Deleted");
if (recycle.isDirectory()) {
int kept = 0;
for (File file : recycle.listFiles()) {
if (file.isDirectory()) {
try {
if (new File(recycle, file.getName() + "/info.json").exists()) {
FileReader reader = new FileReader(new File(recycle, file.getName() + "/info.json"));
YAMLSection info = new YAMLSection(new Gson().fromJson(Util.readAll(reader), Map.class));
reader.close();
if (info.contains("Timestamp")) {
if (TimeUnit.MILLISECONDS.toDays(Calendar.getInstance().getTime().getTime() - info.getLong("Timestamp")) < 7) {
++kept;
continue;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
Directories.delete(file);
} else {
Files.delete(file.toPath());
}
Logger.get("SubServers").info("Removed ./SubServers/Recently Deleted/" + file.getName());
}
if (kept == 0) {
Files.delete(recycle.toPath());
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}, TimeUnit.DAYS.toMillis(7), TimeUnit.DAYS.toMillis(7));
}).run();
new Timer("SubServers.Bungee::Recycle_Cleaner").scheduleAtFixedRate(cleaner, TimeUnit.DAYS.toMillis(7), TimeUnit.DAYS.toMillis(7));
mProxy = new Proxy("(master)");
api.addHostDriver(net.ME1312.SubServers.Bungee.Host.Internal.InternalHost.class, "virtual");
@ -456,8 +445,8 @@ public final class SubProxy extends BungeeCommon implements Listener {
autorun = new LinkedList<String>();
for (String name : this.servers.get().getMap("Servers").getKeys()) {
if (!ukeys.contains(name.toLowerCase())) try {
if (!this.hosts.keySet().contains(this.servers.get().getMap("Servers").getMap(name).getString("Host").toLowerCase())) throw new InvalidServerException("There is no host with this name: " + this.servers.get().getMap("Servers").getMap(name).getString("Host"));
if (exServers.keySet().contains(name.toLowerCase())) {
if (!this.hosts.containsKey(this.servers.get().getMap("Servers").getMap(name).getString("Host").toLowerCase())) throw new InvalidServerException("There is no host with this name: " + this.servers.get().getMap("Servers").getMap(name).getString("Host"));
if (exServers.containsKey(name.toLowerCase())) {
exServers.remove(name.toLowerCase());
servers--;
}
@ -558,7 +547,10 @@ public final class SubProxy extends BungeeCommon implements Listener {
}
ukeys.clear();
if (!posted) Runtime.getRuntime().addShutdownHook(new Thread(this::shutdown, "SubServers.Bungee::System_Shutdown"));
if (!posted) Runtime.getRuntime().addShutdownHook(new Thread(() -> {
shutdown = true;
shutdown();
}, "SubServers.Bungee::System_Shutdown"));
running = ready = true;
legServers.clear();
@ -725,6 +717,7 @@ public final class SubProxy extends BungeeCommon implements Listener {
if (!config.get().getMap("Settings").getStringList("Disabled-Overrides", Collections.emptyList()).contains("/glist"))
getPluginManager().registerCommand(plugin, new SubCommand.BungeeList(this, "glist"));
registerChannel("subservers:input");
getPluginManager().registerCommand(plugin, new SubCommand(this, "subservers"));
getPluginManager().registerCommand(plugin, new SubCommand(this, "subserver"));
getPluginManager().registerCommand(plugin, new SubCommand(this, "sub"));
@ -732,7 +725,14 @@ public final class SubProxy extends BungeeCommon implements Listener {
if (getReconnectHandler() != null && getReconnectHandler().getClass().equals(SmartFallback.class))
setReconnectHandler(new SmartFallback(config.get().getMap("Settings").getMap("Smart-Fallback", new ObjectMap<>()))); // Re-initialize Smart Fallback
if (plugin != null) new Metrics(plugin, 1406).appendAppData();
if (plugin != null) Try.none.run(() -> new Metrics(plugin, 1406)
.addCustomChart(new Metrics.SingleLineChart("managed_hosts", () -> {
return hosts.size();
})).addCustomChart(new Metrics.SingleLineChart("subdata_connected", () -> {
final SubDataServer subdata = this.subdata;
return (subdata != null)? subdata.getClients().size() : 0;
})).addCustomChart(Util.reflect(Metrics.class.getDeclaredField("PLAYER_VERSIONS"), null))
);
new Timer("SubServers.Bungee::Routine_Update_Check").schedule(new TimerTask() {
@SuppressWarnings("unchecked")
@Override
@ -815,7 +815,7 @@ public final class SubProxy extends BungeeCommon implements Listener {
}
private boolean shutdown = false;
protected void shutdown() {
void shutdown() {
if (ready) {
legServers.clear();
legServers.putAll(getServersCopy());
@ -823,7 +823,7 @@ public final class SubProxy extends BungeeCommon implements Listener {
Logger.get("SubServers").info("Stopping hosted servers");
String[] hosts = this.hosts.keySet().toArray(new String[0]);
if (shutdown || !super.isRunning) running = false;
if (shutdown) running = false;
for (String host : hosts) {
api.forceRemoveHost(host);
}
@ -935,21 +935,26 @@ public final class SubProxy extends BungeeCommon implements Listener {
}
}
@SuppressWarnings({"AssignmentUsedAsCondition", "deprecation"})
@EventHandler(priority = Byte.MIN_VALUE)
public void ping_passthrough(ProxyPingEvent e) {
boolean dynamic;
ServerInfo override;
if ((dynamic = SmartFallback.getForcedHost(e.getConnection()) == null) && getReconnectHandler() instanceof SmartFallback && (override = SmartFallback.getDNS(e.getConnection())) != null) {
final boolean dynamic;
if ((dynamic = SmartFallback.getForcedHost(e.getConnection()) == null) || !e.getConnection().getListener().isPingPassthrough()) {
e.getResponse().getPlayers().setOnline(rPlayers.size());
}
final ServerInfo override;
if (dynamic && getReconnectHandler() instanceof SmartFallback && (override = SmartFallback.getDNS(e.getConnection())) != null) {
if (!(override instanceof SubServer) || ((SubServer) override).isRunning()) {
if (!e.getConnection().getListener().isPingPassthrough()) {
e.setResponse(new ServerPing(e.getResponse().getVersion(), e.getResponse().getPlayers(), new TextComponent(override.getMotd()), e.getResponse().getFaviconObject()));
e.getResponse().setDescription(override.getMotd());
} else {
Container<Boolean> lock = new Container<>(true);
boolean mode = plugin != null;
if (mode) e.registerIntent(plugin);
final boolean mode;
final Container<Boolean> lock = new Container<>(true);
if (mode = plugin != null) e.registerIntent(plugin);
((BungeeServerInfo) override).ping((ping, error) -> {
if (error != null) {
e.setResponse(new ServerPing(e.getResponse().getVersion(), e.getResponse().getPlayers(), new TextComponent(getTranslation("ping_cannot_connect")), e.getResponse().getFaviconObject()));
e.getResponse().setDescription(getTranslation("ping_cannot_connect"));
} else e.setResponse(ping);
lock.value = false;
if (mode) e.completeIntent(plugin);
@ -957,28 +962,26 @@ public final class SubProxy extends BungeeCommon implements Listener {
if (!mode) while (lock.value) Try.all.run(() -> Thread.sleep(4));
}
}
} else if (dynamic) {
e.getResponse().getPlayers().setOnline(rPlayers.size());
}
}
@SuppressWarnings("deprecation")
@EventHandler(priority = Byte.MAX_VALUE)
public void ping(ProxyPingEvent e) {
ServerInfo override;
if ((override = SmartFallback.getForcedHost(e.getConnection())) != null || (override = SmartFallback.getDNS(e.getConnection())) != null) {
if ((override = SmartFallback.getForcedHost(e.getConnection())) != null || (getReconnectHandler() instanceof SmartFallback && (override = SmartFallback.getDNS(e.getConnection())) != null)) {
if (override instanceof SubServer && !((SubServer) override).isRunning()) {
e.setResponse(new ServerPing(e.getResponse().getVersion(), e.getResponse().getPlayers(), new TextComponent(api.getLang("SubServers", "Bungee.Ping.Offline")), e.getResponse().getFaviconObject()));
e.getResponse().setDescription(api.getLang("SubServers", "Bungee.Ping.Offline"));
}
} else {
int offline = 0;
for (String name : e.getConnection().getListener().getServerPriority()) {
ServerInfo server = api.getServer(name.toLowerCase());
if (server == null) server = getServerInfo(name);
if (server == null || (server instanceof SubServer && !((SubServer) server).isRunning())) offline++;
ServerInfo server = getServerInfo(name);
if (server instanceof SubServer && !((SubServer) server).isRunning()) ++offline;
}
if (offline >= e.getConnection().getListener().getServerPriority().size()) {
e.setResponse(new ServerPing(e.getResponse().getVersion(), e.getResponse().getPlayers(), new TextComponent(api.getLang("SubServers", "Bungee.Ping.Offline")), e.getResponse().getFaviconObject()));
e.getResponse().setDescription(api.getLang("SubServers", "Bungee.Ping.Offline"));
}
}
}
@ -1002,11 +1005,11 @@ public final class SubProxy extends BungeeCommon implements Listener {
public void validate(ServerConnectEvent e) {
if (e.getPlayer().isConnected()) {
Map<String, ServerInfo> servers = new TreeMap<String, ServerInfo>(api.getServers());
if (servers.keySet().contains(e.getTarget().getName().toLowerCase()) && e.getTarget() != servers.get(e.getTarget().getName().toLowerCase())) {
if (servers.containsKey(e.getTarget().getName().toLowerCase()) && e.getTarget() != servers.get(e.getTarget().getName().toLowerCase())) {
e.setTarget(servers.get(e.getTarget().getName().toLowerCase()));
} else {
servers = getServersCopy();
if (servers.keySet().contains(e.getTarget().getName()) && e.getTarget() != servers.get(e.getTarget().getName())) {
if (servers.containsKey(e.getTarget().getName()) && e.getTarget() != servers.get(e.getTarget().getName())) {
e.setTarget(servers.get(e.getTarget().getName()));
}
}

View File

@ -121,9 +121,9 @@
<archive>
<manifestFile>src/META-INF/MANIFEST.MF</manifestFile>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<descriptors>
<descriptor>../Folia/jar-with-some-dependencies-plus-folia.xml</descriptor>
</descriptors>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
<executions>
@ -155,7 +155,7 @@
<reportOutputDirectory>${basedir}/../../Javadoc/SubServers.Client.Bukkit</reportOutputDirectory>
<additionalOptions>-Xdoclint:none</additionalOptions>
<links>
<link>https://dev.me1312.net/jenkins/job/GalaxiEngine/javadoc/GalaxiUtil/</link>
<link>https://dev.me1312.net/jenkins/job/GalaxiEngine/javadoc/GalaxiBase/</link>
<link>https://dev.me1312.net/jenkins/job/SubData/javadoc/Client/</link>
<link>https://hub.spigotmc.org/javadocs/spigot/</link>
</links>

View File

@ -22,6 +22,7 @@ public class SubAddHostEvent extends Event implements SubEvent {
* @param host Host to be added
*/
public SubAddHostEvent(UUID player, String host) {
super(true);
Util.nullpo(host);
this.player = player;
this.host = host;

View File

@ -18,6 +18,7 @@ public class SubAddProxyEvent extends Event implements SubEvent {
* @param proxy Host Being Added
*/
public SubAddProxyEvent(String proxy) {
super(true);
Util.nullpo(proxy);
this.proxy = proxy;
}

View File

@ -23,6 +23,7 @@ public class SubAddServerEvent extends Event implements SubEvent {
* @param server Server Starting
*/
public SubAddServerEvent(UUID player, String host, String server) {
super(true);
Util.nullpo(server);
this.player = player;
this.host = host;

View File

@ -36,7 +36,8 @@ public class SubCreateEvent extends Event implements SubEvent {
* @param port Server Port Number
*/
public SubCreateEvent(UUID player, String host, String name, String template, Version version, int port, boolean update) {
Util.nullpo(host, name, template, port);
super(true);
Util.nullpo(host, name, template);
this.player = player;
this.update = update;
this.host = host;

View File

@ -37,7 +37,8 @@ public class SubCreatedEvent extends Event implements SubEvent {
* @param port Server Port Number
*/
public SubCreatedEvent(UUID player, String host, String name, String template, Version version, int port, boolean update, boolean success) {
Util.nullpo(host, name, template, port);
super(true);
Util.nullpo(host, name, template);
this.player = player;
this.success = success;
this.update = update;

View File

@ -28,6 +28,7 @@ public class SubEditServerEvent extends Event implements SubEvent {
* @param edit Edit to make
*/
public SubEditServerEvent(UUID player, String server, Pair<String, ?> edit) {
super(true);
Util.nullpo(server, edit);
ObjectMap<String> section = new ObjectMap<String>();
section.set(".", edit.value());

View File

@ -17,6 +17,7 @@ public class SubNetworkConnectEvent extends Event implements SubEvent {
* SubData Network Connect Event
*/
public SubNetworkConnectEvent(DataClient network) {
super(true);
Util.nullpo(network);
this.network = network;
}

View File

@ -19,6 +19,7 @@ public class SubNetworkDisconnectEvent extends Event implements SubEvent {
* SubData Network Disconnect Event
*/
public SubNetworkDisconnectEvent(DataClient network, DisconnectReason reason) {
super(true);
Util.nullpo(network, reason);
this.network = network;
this.reason = reason;

View File

@ -22,6 +22,7 @@ public class SubRemoveHostEvent extends Event implements SubEvent {
* @param host Server Starting
*/
public SubRemoveHostEvent(UUID player, String host) {
super(true);
Util.nullpo(host);
this.player = player;
this.host = host;

View File

@ -18,6 +18,7 @@ public class SubRemoveProxyEvent extends Event implements SubEvent {
* @param proxy Host Being Added
*/
public SubRemoveProxyEvent(String proxy) {
super(true);
Util.nullpo(proxy);
this.proxy = proxy;
}

View File

@ -23,6 +23,7 @@ public class SubRemoveServerEvent extends Event implements SubEvent {
* @param server Server Starting
*/
public SubRemoveServerEvent(UUID player, String host, String server) {
super(true);
Util.nullpo(server);
this.player = player;
this.host = host;

View File

@ -26,6 +26,7 @@ public class SubSendCommandEvent extends Event implements SubEvent {
* @param target Player that will send
*/
public SubSendCommandEvent(UUID player, String server, String command, UUID target) {
super(true);
Util.nullpo(server, command);
this.player = player;
this.server = server;

View File

@ -23,6 +23,7 @@ public class SubStartEvent extends Event implements SubEvent {
* @param server Server Starting
*/
public SubStartEvent(UUID player, String server) {
super(true);
Util.nullpo(server);
this.player = player;
this.server = server;

View File

@ -19,6 +19,7 @@ public class SubStartedEvent extends Event implements SubEvent {
* @param server Server that Started
*/
public SubStartedEvent(String server) {
super(true);
Util.nullpo(server);
this.server = server;
}

View File

@ -25,6 +25,7 @@ public class SubStopEvent extends Event implements SubEvent {
* @param force If it was a Forced Shutdown
*/
public SubStopEvent(UUID player, String server, boolean force) {
super(true);
Util.nullpo(server, force);
this.player = player;
this.server = server;

View File

@ -18,6 +18,7 @@ public class SubStoppedEvent extends Event implements SubEvent {
* @param server Server that Stopped
*/
public SubStoppedEvent(String server) {
super(true);
Util.nullpo(server);
this.server = server;
}

View File

@ -8,6 +8,7 @@ import net.ME1312.Galaxi.Library.Try;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.Galaxi.Library.Version.Version;
import net.ME1312.SubData.Client.SubDataClient;
import net.ME1312.SubServers.Client.Bukkit.Library.Compatibility.AgnosticScheduler;
import net.ME1312.SubServers.Client.Bukkit.Network.Packet.PacketInExRunEvent;
import net.ME1312.SubServers.Client.Bukkit.SubPlugin;
import net.ME1312.SubServers.Client.Common.Network.API.Host;
@ -30,6 +31,7 @@ import org.bukkit.event.player.PlayerQuitEvent;
import java.util.HashMap;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import static net.ME1312.SubServers.Client.Bukkit.Library.ObjectPermission.permits;
@ -49,14 +51,12 @@ public class DefaultUIHandler implements UIHandler, Listener {
* @param plugin Event
*/
public DefaultUIHandler(SubPlugin plugin) {
Util.nullpo(plugin);
this.plugin = plugin;
this.plugin = Util.nullpo(plugin);
Bukkit.getPluginManager().registerEvents(this, plugin);
}
public DefaultUIRenderer getRenderer(Player player) {
if (!gui.containsKey(player.getUniqueId())) gui.put(player.getUniqueId(), new DefaultUIRenderer(plugin, player.getUniqueId()));
return gui.get(player.getUniqueId());
return gui.computeIfAbsent(player.getUniqueId(), k -> new DefaultUIRenderer(plugin, player));
}
public void disable() {
@ -133,7 +133,7 @@ public class DefaultUIHandler implements UIHandler, Listener {
if (m.getString("message").contains(" ")) {
if (!gui.sendTitle(plugin.api.getLang("SubServers", "Interface.Host-Creator.Edit-Name.Invalid-Title"), 4 * 20))
player.sendMessage(plugin.api.getLang("SubServers", "Interface.Host-Creator.Edit-Name.Invalid"));
Bukkit.getScheduler().runTaskLater(plugin, () -> gui.hostCreator((UIRenderer.CreatorOptions) gui.lastVisitedObjects[0]), 4 * 20);
AgnosticScheduler.async.runs(plugin, c -> gui.hostCreator((UIRenderer.CreatorOptions) gui.lastVisitedObjects[0]), 4, TimeUnit.SECONDS);
} else {
gui.setDownloading(plugin.api.getLang("SubServers", "Interface.Generic.Downloading.Response"));
plugin.api.getSubServer(m.getString("message"), server -> {
@ -141,7 +141,7 @@ public class DefaultUIHandler implements UIHandler, Listener {
gui.setDownloading(null);
if (!gui.sendTitle(plugin.api.getLang("SubServers", "Interface.Host-Creator.Edit-Name.Exists-Title"), 4 * 20))
player.sendMessage(plugin.api.getLang("SubServers", "Interface.Host-Creator.Edit-Name.Exists"));
Bukkit.getScheduler().runTaskLater(plugin, () -> gui.hostCreator((UIRenderer.CreatorOptions) gui.lastVisitedObjects[0]), 4 * 20);
AgnosticScheduler.async.runs(plugin, c -> gui.hostCreator((UIRenderer.CreatorOptions) gui.lastVisitedObjects[0]), 4, TimeUnit.SECONDS);
} else {
((UIRenderer.CreatorOptions) gui.lastVisitedObjects[0]).setName(m.getString("message"));
gui.hostCreator((UIRenderer.CreatorOptions) gui.lastVisitedObjects[0]);
@ -173,7 +173,7 @@ public class DefaultUIHandler implements UIHandler, Listener {
} else if (!Try.all.run(() -> Integer.parseInt(m.getString("message"))) || Integer.parseInt(m.getString("message")) <= 0 || Integer.parseInt(m.getString("message")) > 65535) {
if (!gui.sendTitle(plugin.api.getLang("SubServers", "Interface.Host-Creator.Edit-Port.Invalid-Title"), 4 * 20))
player.sendMessage(plugin.api.getLang("SubServers", "Interface.Host-Creator.Edit-Port.Invalid"));
Bukkit.getScheduler().runTaskLater(plugin, () -> gui.hostCreator((UIRenderer.CreatorOptions) gui.lastVisitedObjects[0]), 4 * 20);
AgnosticScheduler.async.runs(plugin, c -> gui.hostCreator((UIRenderer.CreatorOptions) gui.lastVisitedObjects[0]), 4, TimeUnit.SECONDS);
} else {
((UIRenderer.CreatorOptions) gui.lastVisitedObjects[0]).setPort(Integer.valueOf(m.getString("message")));
gui.hostCreator((UIRenderer.CreatorOptions) gui.lastVisitedObjects[0]);
@ -348,7 +348,7 @@ public class DefaultUIHandler implements UIHandler, Listener {
gui.setDownloading(plugin.api.getLang("SubServers", "Interface.Generic.Downloading.Response"));
((SubServer) gui.lastVisitedObjects[0]).start(player.getUniqueId(), response -> {
gui.setDownloading(plugin.api.getLang("SubServers", "Interface.Server-Admin.Start.Title"));
Bukkit.getScheduler().runTaskLater(plugin, gui::reopen, 30);
AgnosticScheduler.async.runs(plugin, c -> gui.reopen(), 1500, TimeUnit.MILLISECONDS);
});
} else gui.reopen();
} else if (item.equals(plugin.api.getLang("SubServers", "Interface.Server-Admin.Stop"))) {
@ -363,7 +363,7 @@ public class DefaultUIHandler implements UIHandler, Listener {
if (listening.value()) if (!json.getString("server").equalsIgnoreCase(((Server) gui.lastVisitedObjects[0]).getName())) {
PacketInExRunEvent.callback("SubStoppedEvent", this);
} else {
Bukkit.getScheduler().runTaskLater(plugin, gui::reopen, 5);
AgnosticScheduler.async.runs(plugin, c -> gui.reopen(), 250, TimeUnit.MILLISECONDS);
}
} catch (Exception e) {}
}
@ -414,6 +414,9 @@ public class DefaultUIHandler implements UIHandler, Listener {
} else if (item.equals(plugin.api.getLang("SubServers", "Interface.Server-Admin.Plugins"))) {
player.closeInventory();
gui.serverPlugin(1, ((Server) gui.lastVisitedObjects[0]).getName());
} else if (item.length() > 2 && item.substring(2).equals(((Server) gui.lastVisitedObjects[0]).getDisplayName()) &&
!item.startsWith(ChatColor.RED.toString()) && !item.startsWith(ChatColor.YELLOW.toString()) && !((Server) gui.lastVisitedObjects[0]).getName().equals(plugin.api.getName())) {
plugin.pmc(player, "Connect", ((Server) gui.lastVisitedObjects[0]).getName());
}
}
} else if (title.startsWith(plugin.api.getLang("SubServers", "Interface.SubServer-Plugin.Title").split("\\$str\\$")[0]) && // SubServer Plugin
@ -497,7 +500,7 @@ public class DefaultUIHandler implements UIHandler, Listener {
*/
@EventHandler
public void close(InventoryCloseEvent event) {
if (gui.keySet().contains(event.getPlayer().getUniqueId())) gui.get(event.getPlayer().getUniqueId()).open = false;
if (gui.containsKey(event.getPlayer().getUniqueId())) gui.get(event.getPlayer().getUniqueId()).open = false;
}
/**
@ -507,7 +510,7 @@ public class DefaultUIHandler implements UIHandler, Listener {
*/
@EventHandler
public void clean(PlayerQuitEvent event) {
if (gui.keySet().contains(event.getPlayer().getUniqueId())) {
if (gui.containsKey(event.getPlayer().getUniqueId())) {
gui.get(event.getPlayer().getUniqueId()).setDownloading(null);
gui.remove(event.getPlayer().getUniqueId());
input.remove(event.getPlayer().getUniqueId());

View File

@ -2,6 +2,7 @@ package net.ME1312.SubServers.Client.Bukkit.Graphic;
import net.ME1312.Galaxi.Library.Container.Container;
import net.ME1312.Galaxi.Library.Container.Value;
import net.ME1312.SubServers.Client.Bukkit.Library.Compatibility.AgnosticScheduler;
import net.ME1312.SubServers.Client.Bukkit.SubPlugin;
import net.ME1312.SubServers.Client.Common.Network.API.Host;
import net.ME1312.SubServers.Client.Common.Network.API.Server;
@ -26,19 +27,15 @@ import static net.ME1312.SubServers.Client.Bukkit.Library.ObjectPermission.permi
* Default GUI Renderer Class
*/
public class DefaultUIRenderer extends UIRenderer {
private static int MAX_VISITED_OBJECTS = 2;
private List<Runnable> windowHistory = new LinkedList<Runnable>();
private static final int MAX_VISITED_OBJECTS = 2;
private final List<Runnable> windowHistory = new LinkedList<Runnable>();
Object[] lastVisitedObjects = new Object[MAX_VISITED_OBJECTS];
int lastPage = 1;
Runnable lastMenu = null;
boolean open = false;
final UUID player;
private SubPlugin plugin;
DefaultUIRenderer(SubPlugin plugin, UUID player) {
DefaultUIRenderer(SubPlugin plugin, Player player) {
super(plugin, player);
this.plugin = plugin;
this.player = player;
}
public void newUI() {
@ -102,7 +99,7 @@ public class DefaultUIRenderer extends UIRenderer {
public void hostMenu(final int page) {
setDownloading(ChatColor.stripColor(plugin.api.getLang("SubServers", "Interface.Host-Menu.Title")));
plugin.api.getHosts(hosts -> plugin.api.getGroups(groups -> {
plugin.api.getHosts(hosts -> plugin.api.getGroups(groups -> AgnosticScheduler.following(player).runs(plugin, c -> {
setDownloading(null);
lastVisitedObjects[0] = null;
lastPage = page;
@ -227,14 +224,14 @@ public class DefaultUIRenderer extends UIRenderer {
inv.setItem(i, block);
}
Bukkit.getPlayer(player).openInventory(inv);
player.openInventory(inv);
open = true;
}));
})));
}
public void hostAdmin(final String name) {
setDownloading(ChatColor.stripColor(plugin.api.getLang("SubServers", "Interface.Host-Admin.Title").replace("$str$", name)));
plugin.api.getHost(name, host -> {
plugin.api.getHost(name, host -> AgnosticScheduler.following(player).runs(plugin, c -> {
windowHistory.add(() -> hostAdmin(name));
if (host == null) {
if (hasHistory()) back();
@ -257,7 +254,7 @@ public class DefaultUIRenderer extends UIRenderer {
i++;
}
Player player = Bukkit.getPlayer(this.player);
Player player = this.player;
if (!permits(name, player, "subservers.host.%.*", "subservers.host.%.create")) {
block = color(7);
blockMeta = block.getItemMeta();
@ -339,10 +336,10 @@ public class DefaultUIRenderer extends UIRenderer {
inv.setItem(35, block);
}
Bukkit.getPlayer(this.player).openInventory(inv);
player.openInventory(inv);
open = true;
}
});
}));
}
public void hostCreator(final CreatorOptions options) {
@ -350,7 +347,7 @@ public class DefaultUIRenderer extends UIRenderer {
if (!options.init()) windowHistory.add(() -> hostCreator(options));
lastVisitedObjects[0] = options;
plugin.api.getHost(options.getHost(), host -> {
plugin.api.getHost(options.getHost(), host -> AgnosticScheduler.following(player).runs(plugin, c -> {
if (host == null || !host.isAvailable() || !host.isEnabled()) {
lastVisitedObjects[0] = null;
if (hasHistory()) back();
@ -466,17 +463,17 @@ public class DefaultUIRenderer extends UIRenderer {
inv.setItem(53, block);
}
Bukkit.getPlayer(player).openInventory(inv);
player.openInventory(inv);
open = true;
}
});
}));
}
public void hostCreatorTemplates(final int page, final CreatorOptions options) {
setDownloading(ChatColor.stripColor(plugin.api.getLang("SubServers", "Interface.Host-Creator.Edit-Template.Title").replace("$str$", options.getHost())));
options.init();
lastVisitedObjects[0] = options;
plugin.api.getHost(options.getHost(), host -> {
plugin.api.getHost(options.getHost(), host -> AgnosticScheduler.following(player).runs(plugin, c -> {
if (host == null || !host.isAvailable() || !host.isEnabled()) {
lastVisitedObjects[0] = null;
if (hasHistory()) back();
@ -579,15 +576,15 @@ public class DefaultUIRenderer extends UIRenderer {
inv.setItem(i, block);
}
Bukkit.getPlayer(player).openInventory(inv);
player.openInventory(inv);
open = true;
}
});
}));
}
public void hostPlugin(final int page, final String name) {
setDownloading(ChatColor.stripColor(plugin.api.getLang("SubServers", "Interface.Host-Plugin.Title").replace("$str$", name)));
plugin.api.getHost(name, host -> {
plugin.api.getHost(name, host -> AgnosticScheduler.following(player).runs(plugin, c -> {
windowHistory.add(() -> hostPlugin(page, name));
if (host == null) {
if (hasHistory()) back();
@ -687,15 +684,15 @@ public class DefaultUIRenderer extends UIRenderer {
inv.setItem(i, block);
}
Bukkit.getPlayer(player).openInventory(inv);
player.openInventory(inv);
open = true;
}
});
}));
}
public void groupMenu(final int page) {
setDownloading(ChatColor.stripColor(plugin.api.getLang("SubServers", "Interface.Group-Menu.Title")));
plugin.api.getServers(servers -> {
plugin.api.getServers(servers -> AgnosticScheduler.following(player).runs(plugin, c -> {
setDownloading(null);
lastVisitedObjects[0] = null;
lastPage = page;
@ -713,12 +710,12 @@ public class DefaultUIRenderer extends UIRenderer {
} else {
for (String name : sgl) {
String group = name;
if (conflitresolver.keySet().contains(name.toLowerCase())) {
if (conflitresolver.containsKey(name.toLowerCase())) {
group = conflitresolver.get(name.toLowerCase());
} else {
conflitresolver.put(name.toLowerCase(), name);
}
List<Server> list = (groups.keySet().contains(group))? groups.get(group) : new ArrayList<Server>();
List<Server> list = (groups.containsKey(group))? groups.get(group) : new ArrayList<Server>();
list.add(server);
groups.put(group, list);
}
@ -820,16 +817,16 @@ public class DefaultUIRenderer extends UIRenderer {
inv.setItem(i, block);
}
Bukkit.getPlayer(player).openInventory(inv);
player.openInventory(inv);
open = true;
});
}));
}
public void serverMenu(final int page, final String host, final String group) {
setDownloading(ChatColor.stripColor((host == null)?((group == null)?plugin.api.getLang("SubServers", "Interface.Server-Menu.Title"):((group.length() == 0)?plugin.api.getLang("SubServers", "Interface.Group-SubServer.Title-Ungrouped"):plugin.api.getLang("SubServers", "Interface.Group-SubServer.Title").replace("$str$", group))):plugin.api.getLang("SubServers", "Interface.Host-SubServer.Title").replace("$str$", host)));
Value<String> hostname = new Container<String>(host);
Value<List<Server>> servercontainer = new Container<List<Server>>(new LinkedList<Server>());
Runnable renderer = () -> {
Runnable renderer = () -> AgnosticScheduler.following(player).runs(plugin, c -> {
setDownloading(null);
lastPage = page;
@ -985,9 +982,9 @@ public class DefaultUIRenderer extends UIRenderer {
inv.setItem(i, block);
}
Bukkit.getPlayer(player).openInventory(inv);
player.openInventory(inv);
open = true;
};
});
if (host != null && host.length() > 0) {
plugin.api.getHost(host, object -> {
@ -1018,7 +1015,7 @@ public class DefaultUIRenderer extends UIRenderer {
public void serverAdmin(final String name) {
setDownloading(ChatColor.stripColor(plugin.api.getLang("SubServers", "Interface.Server-Admin.Title").replace("$str$", name)));
BiConsumer<Server, Host> renderer = (server, host) -> {
BiConsumer<Server, Host> renderer = (server, host) -> AgnosticScheduler.following(player).runs(plugin, c -> {
setDownloading(null);
lastVisitedObjects[0] = server;
ItemStack block;
@ -1038,7 +1035,7 @@ public class DefaultUIRenderer extends UIRenderer {
}
i = 0;
Player player = Bukkit.getPlayer(this.player);
Player player = this.player;
if (host == null || ((SubServer) server).isRunning()) {
if (host == null || !permits(server, player, "subservers.subserver.%.*", "subservers.subserver.%.terminate")) {
block = color(7);
@ -1226,7 +1223,7 @@ public class DefaultUIRenderer extends UIRenderer {
player.openInventory(inv);
open = true;
};
});
plugin.api.getServer(name, server -> {
windowHistory.add(() -> serverAdmin(name));
@ -1250,7 +1247,7 @@ public class DefaultUIRenderer extends UIRenderer {
public void serverPlugin(final int page, final String name) {
setDownloading(ChatColor.stripColor(plugin.api.getLang("SubServers", "Interface.SubServer-Plugin.Title").replace("$str$", name)));
plugin.api.getServer(name, server -> {
plugin.api.getServer(name, server -> AgnosticScheduler.following(player).runs(plugin, c -> {
windowHistory.add(() -> serverPlugin(page, name));
if (server == null) {
if (hasHistory()) back();
@ -1350,9 +1347,9 @@ public class DefaultUIRenderer extends UIRenderer {
inv.setItem(i, block);
}
Bukkit.getPlayer(player).openInventory(inv);
player.openInventory(inv);
open = true;
}
});
}));
}
}

View File

@ -2,22 +2,29 @@ package net.ME1312.SubServers.Client.Bukkit.Graphic;
import net.ME1312.Galaxi.Library.Container.ContainedPair;
import net.ME1312.Galaxi.Library.Container.Container;
import net.ME1312.Galaxi.Library.Try;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.Galaxi.Library.Version.Version;
import net.ME1312.SubServers.Client.Bukkit.Library.Compatibility.AgnosticScheduler;
import net.ME1312.SubServers.Client.Bukkit.SubPlugin;
import net.ME1312.SubServers.Client.Common.Network.API.Host;
import net.ME1312.SubServers.Client.Common.Network.API.Server;
import net.ME1312.SubServers.Client.Common.Network.API.SubServer;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.*;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.PrimitiveIterator.OfInt;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -28,14 +35,17 @@ public abstract class UIRenderer {
private final boolean USE_TITLES;
private final boolean TAPI_1_11;
private final boolean TAPI_PLUGIN;
private final MethodHandle MAPI_1_13;
static final HashMap<String, PluginRenderer<Host>> hostPlugins = new HashMap<String, PluginRenderer<Host>>();
static final HashMap<String, PluginRenderer<Server>> serverPlugins = new HashMap<String, PluginRenderer<Server>>();
private ContainedPair<String, Integer> tdownload = null;
private final String[] adownload;
private int download = -1;
private final UUID player;
private SubPlugin plugin;
private final String[] downloadA;
private final int downloadL;
private int downloadF;
private String downloadT;
private Runnable download;
final Player player;
final SubPlugin plugin;
/**
* Creates a new UIRenderer
@ -43,11 +53,18 @@ public abstract class UIRenderer {
* @param plugin SubPlugin
* @param player Player
*/
public UIRenderer(SubPlugin plugin, UUID player) {
public UIRenderer(SubPlugin plugin, Player player) {
Util.nullpo(plugin, player);
this.plugin = plugin;
this.player = player;
// Detect Material API
if (plugin.api.getGameVersion().compareTo(new Version("1.13")) < 0) {
MAPI_1_13 = null;
} else {
MAPI_1_13 = Try.all.get(() -> MethodHandles.publicLookup().findStatic(Material.class, "getMaterial", MethodType.methodType(Material.class, new Class[]{ String.class, boolean.class})));
}
// Detect Title API
if (USE_TITLES = plugin.config.get().getMap("Settings").getBoolean("Use-Title-Messages", true)) {
if (TAPI_1_11 = plugin.api.getGameVersion().compareTo(new Version("1.11")) >= 0) {
@ -59,7 +76,7 @@ public abstract class UIRenderer {
TAPI_1_11 = TAPI_PLUGIN = false;
}
// Pre-render Animations
// Pre-render Animation
{
String a = plugin.api.getLang("SubServers", "Interface.Generic.Downloading.Title-Color-Alt");
String b = plugin.api.getLang("SubServers", "Interface.Generic.Downloading.Title-Color");
@ -93,7 +110,7 @@ public abstract class UIRenderer {
break;
}
} while (true);
adownload = frames.toArray(new String[0]);
downloadL = (downloadA = frames.toArray(new String[0])).length;
}
}
@ -186,25 +203,22 @@ public abstract class UIRenderer {
* @return Success Status
*/
public boolean sendTitle(String line1, String line2, int fadein, int stay, int fadeout) {
if (USE_TITLES) {
if (USE_TITLES && player.isOnline()) {
try {
Player player = Bukkit.getPlayer(this.player);
if (player != null) {
if (TAPI_1_11) {
if (line1 == null) {
player.resetTitle();
} else {
player.sendTitle(line1, line2, (fadein >= 0)?fadein:10, (stay >= 0)?stay:70, (fadeout >= 0)?fadeout:20);
}
return true;
} else if (TAPI_PLUGIN) {
if (line1 == null) {
com.connorlinfoot.titleapi.TitleAPI.clearTitle(player);
} else {
com.connorlinfoot.titleapi.TitleAPI.sendTitle(player, (fadein >= 0)?fadein:10, (stay >= 0)?stay:70, (fadeout >= 0)?fadeout:20, line1, line2);
}
return true;
if (TAPI_1_11) {
if (line1 == null) {
player.resetTitle();
} else {
player.sendTitle(line1, line2, (fadein >= 0)?fadein:10, (stay >= 0)?stay:70, (fadeout >= 0)?fadeout:20);
}
return true;
} else if (TAPI_PLUGIN) {
if (line1 == null) {
com.connorlinfoot.titleapi.TitleAPI.clearTitle(player);
} else {
com.connorlinfoot.titleapi.TitleAPI.sendTitle(player, (fadein >= 0)?fadein:10, (stay >= 0)?stay:70, (fadeout >= 0)?fadeout:20, line1, line2);
}
return true;
}
} catch (Throwable e) {
return false;
@ -228,50 +242,50 @@ public abstract class UIRenderer {
* @param subtitle Subtitle to display (or null to hide)
*/
public void setDownloading(String subtitle) {
if (subtitle != null) {
if (!canSendTitle()) {
final String text = subtitle;
if (download != -1) Bukkit.getScheduler().cancelTask(download);
download = Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, () -> {
if (tdownload != null) Bukkit.getPlayer(player).sendMessage(plugin.api.getLang("SubServers", "Interface.Generic.Downloading").replace("$str$", text));
download = -1;
}, 50L);
return;
}
if (player.isOnline()) {
if (subtitle != null) {
if (!canSendTitle()) {
final String text = subtitle;
if (download != null) download.run();
download = AgnosticScheduler.following(player).runs(plugin, cancel -> {
if (downloadT != null && player.isOnline()) player.sendMessage(plugin.api.getLang("SubServers", "Interface.Generic.Downloading").replace("$str$", text));
download = null;
}, 2500, TimeUnit.MILLISECONDS);
return;
}
if (!subtitle.startsWith(Character.toString(ChatColor.COLOR_CHAR))) {
subtitle = plugin.api.getLang("SubServers", "Interface.Generic.Downloading.Title-Color-Alt") + subtitle;
}
if (tdownload == null) {
tdownload = new ContainedPair<String, Integer>(subtitle, 0);
if (!subtitle.startsWith(Character.toString(ChatColor.COLOR_CHAR))) {
subtitle = plugin.api.getLang("SubServers", "Interface.Generic.Downloading.Title-Color-Alt") + subtitle;
}
if (downloadT == null) {
downloadT = subtitle;
downloadF = 0;
new BukkitRunnable() {
@Override
public void run() {
if (tdownload != null) {
if (++tdownload.value >= adownload.length) {
tdownload.value = 0;
AgnosticScheduler.following(player).repeats(plugin, cancel -> {
if (downloadT != null) {
if (++downloadF >= downloadL) {
downloadF = 0;
}
if (!sendTitle(adownload[tdownload.value], tdownload.key, 0, 10, 5)) {
cancel();
if (!sendTitle(downloadA[downloadF], downloadT, 0, 10, 5)) {
cancel.run();
}
} else {
sendTitle(null);
cancel();
cancel.run();
}
}
}.runTaskTimer(plugin, 0, 1);
}, 0, 50, TimeUnit.MILLISECONDS);
} else {
downloadT = subtitle;
}
} else {
tdownload.key = subtitle;
}
} else {
if (tdownload != null) {
tdownload = null;
}
if (download != -1) {
Bukkit.getScheduler().cancelTask(download);
download = -1;
if (downloadT != null) {
downloadT = null;
}
if (download != null) {
download.run();
download = null;
}
}
}
}
@ -296,7 +310,7 @@ public abstract class UIRenderer {
@SuppressWarnings({"deprecation", "JavaReflectionMemberAccess"})
public ItemStack parseItem(String str, ItemStack def) {
final Container<String> item = new Container<String>(str);
if (plugin.api.getGameVersion().compareTo(new Version("1.13")) < 0) {
if (MAPI_1_13 == null) {
try {
// int
Matcher matcher = Pattern.compile("(?i)^(\\d+)$").matcher(item.value);
@ -332,15 +346,16 @@ public abstract class UIRenderer {
}
// Material Name
if (plugin.api.getGameVersion().compareTo(new Version("1.13")) < 0) {
if (MAPI_1_13 == null) {
try {
return new ItemStack(Material.valueOf(item.value.toUpperCase()), 1);
} catch (IllegalArgumentException e) {}
} else try {
if (Material.class.getMethod("getMaterial", String.class, boolean.class).invoke(null, item.value.toUpperCase(), false) != null) {
return new ItemStack((Material) Material.class.getMethod("getMaterial", String.class, boolean.class).invoke(null, item.value.toUpperCase(), false), 1);
Material material = (Material) MAPI_1_13.invokeExact(item.value.toUpperCase(), false);
if (material != null) {
return new ItemStack(material, 1);
}
} catch (Exception e) {}
} catch (Throwable e) {}
return def;
}

View File

@ -0,0 +1,154 @@
package net.ME1312.SubServers.Client.Bukkit.Library.Compatibility;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.plugin.Plugin;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
/**
* Folia Regional Scheduling Compatibility Class
*/
public abstract class AgnosticScheduler {
/**
* Provides an asynchronous thread scheduler (in both folia and bukkit)
*/
public static final AgnosticScheduler async = async();
private static native AgnosticScheduler async();
/**
* Provides the folia global region scheduler / bukkit main thread scheduler
*/
public static final AgnosticScheduler global = global();
private static native AgnosticScheduler global();
/**
* Provides a folia region scheduler / bukkit main thread scheduler
*
* @param block Block
* @return Platform-agnostic Scheduler
*/
public static native AgnosticScheduler at(Block block);
/**
* Provides a folia region scheduler / bukkit main thread scheduler
*
* @param location Block location
* @return Platform-agnostic Scheduler
*/
public static native AgnosticScheduler at(Location location);
/**
* Provides a folia region scheduler / bukkit main thread scheduler
*
* @param world Block world
* @param x Block x coordinate
* @param z Block z coordinate
* @return Platform-agnostic Scheduler
*/
public static native AgnosticScheduler at(World world, int x, int z);
/**
* Provides a folia region scheduler / bukkit main thread scheduler
*
* @param chunk Chunk
* @return Platform-agnostic Scheduler
*/
public static native AgnosticScheduler atChunk(Chunk chunk);
/**
* Provides a folia region scheduler / bukkit main thread scheduler
*
* @param world Chunk world
* @param cx Chunk x coordinate
* @param cz Chunk z coordinate
* @return Platform-agnostic Scheduler
*/
public static native AgnosticScheduler atChunk(World world, int cx, int cz);
/**
* Provides a folia entity scheduler / bukkit main thread scheduler
*
* @param entity Entity
* @return Platform-agnostic Scheduler
*/
public static native AgnosticScheduler following(Entity entity);
/**
* Schedules a 1-time task that runs immediately
*
* @param plugin Plugin
* @param task Task (consumes a task cancellation runnable)
* @return A Runnable that can currently be used to cancel the task
*/
public abstract Runnable runs(Plugin plugin, Consumer<Runnable> task);
/**
* Schedules a 1-time task that runs after a number of ticks
*
* @param plugin Plugin
* @param task Task (consumes a task cancellation runnable)
* @param delay Delay in ticks
* @return A Runnable that can currently be used to cancel the task
*/
public abstract Runnable runs(Plugin plugin, Consumer<Runnable> task, long delay);
/**
* Schedules a 1-time task that runs after a number of timeunits
*
* @param plugin Plugin
* @param task Task (consumes a task cancellation runnable)
* @param delay Delay
* @param units Time units
* @return A Runnable that can currently be used to cancel the task
*/
public native Runnable runs(Plugin plugin, Consumer<Runnable> task, long delay, TimeUnit units);
/**
* Schedules a repeating task that runs after a number of ticks
*
* @param plugin Plugin
* @param task Task (consumes a task cancellation runnable)
* @param repeat Repeat delay in ticks
* @return A Runnable that can currently be used to cancel the task
*/
public native Runnable repeats(Plugin plugin, Consumer<Runnable> task, long repeat);
/**
* Schedules a repeating task that runs after a number of timeunits
*
* @param plugin Plugin
* @param task Task (consumes a task cancellation runnable)
* @param repeat Repeat delay
* @param units Time units
* @return A Runnable that can currently be used to cancel the task
*/
public native Runnable repeats(Plugin plugin, Consumer<Runnable> task, long repeat, TimeUnit units);
/**
* Schedules a repeating task that runs after a number of ticks
*
* @param plugin Plugin
* @param task Task (consumes a task cancellation runnable)
* @param delay Initial delay in ticks
* @param repeat Repeat delay in ticks
* @return A Runnable that can currently be used to cancel the task
*/
public abstract Runnable repeats(Plugin plugin, Consumer<Runnable> task, long delay, long repeat);
/**
* Schedules a repeating task that runs after a number of timeunits
*
* @param plugin Plugin
* @param task Task (consumes a task cancellation runnable)
* @param delay Initial delay
* @param repeat Repeat delay
* @param units Time units
* @return A Runnable that can currently be used to cancel the task
*/
public native Runnable repeats(Plugin plugin, Consumer<Runnable> task, long delay, long repeat, TimeUnit units);
}

View File

@ -17,6 +17,9 @@ import java.text.DecimalFormat;
import java.util.LinkedList;
import java.util.List;
/**
* BungeeCord Chat Library Compatibility Class
*/
public class BungeeChat {
private SubPlugin plugin;
@ -24,6 +27,9 @@ public class BungeeChat {
this.plugin = plugin;
}
/**
* Output for <b>/sub list</b>
*/
public void listCommand(CommandSender sender, String label) {
plugin.api.getGroups(groups -> plugin.api.getHosts(hosts -> plugin.api.getServers(servers -> plugin.api.getMasterProxy(proxymaster -> plugin.api.getProxies(proxies -> {
int i = 0;

View File

@ -0,0 +1,72 @@
package net.ME1312.SubServers.Client.Bukkit.Library.Compatibility;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import java.util.Objects;
import java.util.UUID;
/**
* Offline Block Location Class
*/
public class OfflineBlock {
public final UUID world;
public final int x, y, z;
/**
* Convert an existing location object
*
* @param location Location
*/
public OfflineBlock(Location location) {
this(location.getWorld().getUID(), location.getBlockX(), location.getBlockY(), location.getBlockZ());
}
/**
* Store location data
*
* @param world World ID
* @param x X position
* @param y Y position
* @param z Z position
*/
public OfflineBlock(UUID world, int x, int y, int z) {
this.world = world;
this.x = x;
this.y = y;
this.z = z;
}
/**
* Find the World if loaded
*
* @return World (or null if unavailable)
*/
public World world() {
return Bukkit.getWorld(this.world);
}
/**
* Find the Location if loaded
*
* @return Location (or null if unavailable)
*/
public Location load() {
World world = Bukkit.getWorld(this.world);
return (world == null)? null : new Location(world, x, y, z);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
OfflineBlock that = (OfflineBlock) o;
return x == that.x && y == that.y && z == that.z && Objects.equals(world, that.world);
}
@Override
public int hashCode() {
return Objects.hash(world, x, y, z);
}
}

View File

@ -1,39 +1,18 @@
package net.ME1312.SubServers.Client.Bukkit.Library.Compatibility;
import net.ME1312.Galaxi.Library.Container.ContainedPair;
import net.ME1312.Galaxi.Library.Container.Pair;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.Galaxi.Library.Try;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubServers.Client.Bukkit.Event.*;
import net.ME1312.SubServers.Client.Bukkit.SubAPI;
import net.ME1312.SubServers.Client.Bukkit.SubPlugin;
import net.ME1312.SubServers.Client.Common.Network.API.*;
import me.clip.placeholderapi.PlaceholderAPI;
import me.clip.placeholderapi.expansion.Cacheable;
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
import me.clip.placeholderapi.expansion.Taskable;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.scheduler.BukkitTask;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* PlaceholderAPI Implementation Class
*/
public class PlaceholderImpl extends PlaceholderExpansion implements Taskable, Cacheable {
private SubPlugin plugin;
private BukkitTask task;
private Cache cache;
private boolean init;
/**
* Create a PlaceholderAPI Implementation Instance
@ -42,14 +21,8 @@ public class PlaceholderImpl extends PlaceholderExpansion implements Taskable, C
*/
public PlaceholderImpl(SubPlugin plugin) {
this.plugin = plugin;
this.cache = new Cache();
this.init = false;
if (plugin.config.get().getMap("Settings").getBoolean("PlaceholderAPI-Ready", false)) init();
}
@Override
public String getIdentifier() {
return "subservers";
@ -70,21 +43,6 @@ public class PlaceholderImpl extends PlaceholderExpansion implements Taskable, C
return true;
}
private void init() {
if (!init) {
init = true;
Bukkit.getPluginManager().registerEvents(cache.events, plugin);
Bukkit.getScheduler().runTaskLater(plugin, () -> {
if (task == null) {
int interval = plugin.config.get().getMap("Settings").getInt("PlaceholderAPI-Cache-Interval", 300);
int start = interval - new Random().nextInt((interval / 3) + 1); // Don't have all servers request at the same time
task = Bukkit.getScheduler().runTaskTimer(plugin, cache::refresh, 20L * start, 20L * interval);
cache.refresh();
}
}, 120L);
}
}
@Override
public void start() {
// do nothing
@ -92,17 +50,12 @@ public class PlaceholderImpl extends PlaceholderExpansion implements Taskable, C
@Override
public void stop() {
if (task != null) {
try {
task.cancel();
} catch (Throwable exception) {}
task = null;
}
plugin.phi.stop();
}
@Override
public void clear() {
cache.reset();
plugin.phi.clear();
}
@Override
@ -112,679 +65,6 @@ public class PlaceholderImpl extends PlaceholderExpansion implements Taskable, C
@Override
public String onRequest(OfflinePlayer player, String request) {
boolean colored = !request.startsWith("plain_");
if (!colored || request.startsWith("color_")) request = request.substring(6);
String response = runMethod(player, request);
if (!init) init();
if (response != null && !colored) {
return ChatColor.stripColor(response);
} else {
return response;
}
}
private static final Pattern replacements = Pattern.compile("#?([^\\s#]+?\\(.*?\\))|\\$([^$]+)\\$", Pattern.CASE_INSENSITIVE);
private String[] arguments(OfflinePlayer player, String text, boolean replace) {
LinkedList<String> arguments = new LinkedList<>();
if (text != null && !text.isEmpty()) {
Pattern p = replacements;
Matcher m = p.matcher(text);
StringBuilder argument = new StringBuilder();
while (m.find()) {
String[] replacement = findMethod(player, text, m.start(), replace);
if (replacement[0].contains(",")) {
String[] s = replacement[0].split(",");
argument.append(s[0]);
arguments.add(argument.toString().trim());
for (int i = 1; i < s.length - 1; ++i) {
arguments.add(s[i].trim());
}
argument = new StringBuilder();
argument.append(s[s.length - 1]);
} else {
argument.append(replacement[0]);
}
argument.append(replacement[1]);
text = replacement[2];
m = p.matcher(text);
}
if (text.contains(",")) {
String[] s = text.split(",");
argument.append(s[0]);
arguments.add(argument.toString().trim());
argument = null;
for (int i = 1; i < s.length; ++i) {
arguments.add(s[i].trim());
}
} else if (text.length() > 0) {
argument.append(text);
}
if (argument != null && argument.length() > 0) {
arguments.add(argument.toString().trim());
}
}
return arguments.toArray(new String[0]);
}
private String replace(OfflinePlayer player, String text) {
if (text != null) {
Pattern p = replacements;
Matcher m = p.matcher(text);
StringBuilder str = new StringBuilder();
while (m.find()) {
String[] replacement = findMethod(player, text, m.start(), true);
str.append(replacement[0]);
str.append(replacement[1]);
text = replacement[2];
m = p.matcher(text);
}
str.append(text);
return str.toString();
} else {
return null;
}
}
private String[] findMethod(OfflinePlayer player, String text, int start, boolean run) {
String[] values = new String[3];
values[0] = text.substring(0, start);
text = text.substring(start);
int[] open = {'(', '<'};
int[] close = {')', '>'};
Arrays.sort(open);
Arrays.sort(close);
int i = -1;
if (text.codePointAt(0) == '$') {
Matcher m = Pattern.compile("^\\$([^$]+)\\$", Pattern.CASE_INSENSITIVE).matcher(text);
if (m.find()) {
String str = '%' + m.group(1) + '%';
text = text.substring(m.end());
if (run) {
String response = PlaceholderAPI.setPlaceholders(player, str);
values[1] = (response == null)?m.group():response;
} else {
values[1] = m.group();
}
}
} else {
++i;
boolean responses = false;
StringBuilder str = new StringBuilder();
for (int level = 0; i < text.codePoints().count(); ++i) {
int c = text.codePointAt(i);
str.appendCodePoint(c);
if (Arrays.binarySearch(open, c) >= 0) {
++level;
} else if (Arrays.binarySearch(close, c) >= 0) {
--level;
if (level <= 0) {
if (responses) break;
boolean more = false;
for (int ix = i + 1; ix < text.codePoints().count(); ++ix) {
int cx = text.codePointAt(ix);
if (!Character.isWhitespace(cx) && cx != '_') {
more = cx == '<';
break;
}
}
if (!more) break;
else responses = true;
}
}
}
if (run) {
String response = runMethod(player, str.toString());
values[1] = (response == null)?str.toString():response;
} else {
values[1] = str.toString();
}
}
StringBuilder str = new StringBuilder();
for (i += 1; i < text.codePoints().count(); ++i) {
str.appendCodePoint(text.codePointAt(i));
}
values[2] = str.toString();
return values;
}
private String[] parseMethod(OfflinePlayer player, String text) {
Matcher m = Pattern.compile("^#?(.+?)(?:[\\s_]*\\((.*?)\\))?(?:[\\s_]*<(.*)>)?$", Pattern.CASE_INSENSITIVE).matcher(text);
if (m.find()) {
String[] values = new String[3];
values[0] = m.group(1);
if (m.group(2) == null || m.group(2).trim().isEmpty() ||
m.group(3) == null || m.group(3).trim().isEmpty()) {
// Simple parsing: () or <>
values[1] = m.group(2);
values[2] = m.group(3);
} else {
// Complex parsing: () and <>
text = text.substring(m.end(1));
int stage = 1, level = 0, i = 0;
char open = '(', close = ')';
boolean responses = false;
StringBuilder str = new StringBuilder();
for (; i < text.codePoints().count(); ++i) {
int c = text.codePointAt(i);
if (c == open) {
if (level > 0) str.appendCodePoint(c);
++level;
} else if (c == close) {
--level;
if (level > 0) str.appendCodePoint(c);
else {
if (responses) break;
boolean more = false;
for (int ix = i + 1; ix < text.codePoints().count(); ++ix) {
int cx = text.codePointAt(ix);
if (!Character.isWhitespace(cx) && cx != '_') {
more = cx == '<';
break;
}
}
if (!more) break;
else {
responses = true;
open = '<'; close = '>';
values[stage++] = str.toString();
str = new StringBuilder();
}
}
} else {
if (level > 0) str.appendCodePoint(c);
}
}
values[stage] = str.toString();
if (level > 0 || ++i < text.codePoints().count()) {
return null;
}
}
return values;
} else {
return null;
}
}
private String runMethod(OfflinePlayer player, String text) {
String[] parsed = parseMethod(player, text);
if (parsed != null) {
String method = parsed[0];
String[] args = arguments(player, parsed[1], true);
String[] responses = arguments(player, parsed[2], false);
for (int i = 0; i < responses.length; ++i)
responses[i] = ChatColor.translateAlternateColorCodes('&', responses[i].trim());
return replace(player, runMethod(player, method, args, responses));
} else {
return null;
}
}
@SuppressWarnings("ConstantConditions")
private String runMethod(OfflinePlayer player, String method, String[] args, String[] responses) {
Server server = (plugin.api.getName() != null)? cache.getServer(plugin.api.getName()) : null;
SubServer subserver = (server instanceof SubServer)? (SubServer) server : null;
Pair<String, List<Server>> group = null;
Host host = (subserver != null)? cache.getHost(subserver.getHost()) : null;
Proxy proxy = cache.getMasterProxy();
method = method.toLowerCase();
if (method.startsWith("proxy.")) {
if (args.length > 0 && !args[0].isEmpty()) proxy = cache.getProxy(args[0]);
if (proxy == null) return null;
} else if (method.startsWith("host.")) {
if (args.length > 0 && !args[0].isEmpty()) host = cache.getHost(args[0]);
if (host == null) return null;
} else if (method.startsWith("group.")) {
if (args.length > 0 && !args[0].isEmpty()) group = cache.getGroup(args[0]);
// if (group == null) return null; // Empty groups are null
} else if (method.startsWith("server.")) {
if (args.length > 0 && !args[0].isEmpty()) server = cache.getServer(args[0]);
if (server == null) return null;
} else if (method.startsWith("subserver.")) {
if (args.length > 0 && !args[0].isEmpty()) server = subserver = cache.getSubServer(args[0]);
if (subserver == null) return null;
}
// --- Methods where Objects link to other Objects --
if (method.startsWith("subserver.host")) {
if (method.equals("subserver.host")) {
return subserver.getHost();
} else {
LinkedList<String> arguments = new LinkedList<String>();
arguments.addAll(Arrays.asList(args));
if (args.length > 0) arguments.removeFirst();
arguments.addFirst(subserver.getHost());
return runMethod(player, method.substring(10), arguments.toArray(new String[0]), responses);
}
} else if (method.startsWith("subserver.template")) {
if (method.equals("subserver.template")) {
return (subserver.getTemplate() != null)?subserver.getTemplate():defaults(responses, "(custom)")[0];
} else if (subserver.getTemplate() != null) {
LinkedList<String> arguments = new LinkedList<String>();
arguments.addAll(Arrays.asList(args));
if (args.length > 0) arguments.removeFirst();
arguments.addFirst(subserver.getTemplate());
arguments.addFirst(subserver.getHost());
return runMethod(player, "host.creator." + method.substring(10), arguments.toArray(new String[0]), responses);
} else {
return null;
}
} else switch (method) { // --- Straight up Methods ---
case "example": {
return defaults(responses, ChatColor.LIGHT_PURPLE+"Example!")[0];
}
case "players": {
int i = cache.getMasterProxy().getPlayers().size();
for (Proxy p : cache.getProxies().values()) i += p.getPlayers().size();
return Integer.toString(i);
}
case "proxy":
case "proxies": {
return Integer.toString(cache.getProxies().size() + 1);
}
case "proxy.displayname": {
return proxy.getDisplayName();
}
case "proxy.type": {
return defaults(responses, "Master Proxy", "Proxy") [((proxy.isMaster())?0:1)];
}
case "proxy.players": {
return Integer.toString(proxy.getPlayers().size());
}
case "proxy.subdata": {
return defaults(responses, ChatColor.GREEN+"Connected", ChatColor.RED+"Disconnected") [(proxy.getSubData()[0] == null)?1:0];
}
case "proxy.subdata.channels":
case "proxy.subdata.subchannels": {
return Integer.toString(proxy.getSubData().length - ((method.endsWith(".subchannels"))?1:0));
}
case "proxy.signature": {
return proxy.getSignature();
}
case "host":
case "hosts": {
return Integer.toString(cache.getHosts().size());
}
case "host.displayname": {
return host.getDisplayName();
}
case "host.available": {
return defaults(responses, ChatColor.GREEN+"Available", ChatColor.RED+"Unavailable") [(host.isAvailable())?0:1];
}
case "host.enabled": {
return defaults(responses, ChatColor.GREEN+"Enabled", ChatColor.RED+"Disabled") [(host.isEnabled())?0:1];
}
case "host.address": {
return host.getAddress().getHostAddress();
}
case "host.creator.template":
case "host.subcreator.template":
case "host.creator.templates":
case "host.subcreator.templates": {
return Integer.toString(host.getCreator().getTemplates().size());
}
case "host.creator.template.displayname":
case "host.subcreator.template.displayname": {
SubCreator.ServerTemplate template = (args.length > 1 && !args[1].isEmpty())? host.getCreator().getTemplate(args[1]) : null;
if (template != null) return template.getDisplayName();
else return null;
}
case "host.creator.template.enabled":
case "host.subcreator.template.enabled": {
SubCreator.ServerTemplate template = (args.length > 1 && !args[1].isEmpty())? host.getCreator().getTemplate(args[1]) : null;
if (template != null) return defaults(responses, ChatColor.GREEN+"Enabled", ChatColor.RED+"Disabled") [((template.isEnabled())?0:1)];
else return null;
}
case "host.creator.template.type":
case "host.subcreator.template.type": {
SubCreator.ServerTemplate template = (args.length > 1 && !args[1].isEmpty())? host.getCreator().getTemplate(args[1]) : null;
if (template != null) return template.getType().toString();
else return null;
}
case "host.creator.template.requiresversion":
case "host.subcreator.template.requiresversion": {
SubCreator.ServerTemplate template = (args.length > 1 && !args[1].isEmpty())? host.getCreator().getTemplate(args[1]) : null;
if (template != null) return defaults(responses, ChatColor.GREEN+"Optional", ChatColor.YELLOW+"Required") [((template.requiresVersion())?1:0)];
else return null;
}
case "host.creator.template.updatable":
case "host.subcreator.template.updatable": {
SubCreator.ServerTemplate template = (args.length > 1 && !args[1].isEmpty())? host.getCreator().getTemplate(args[1]) : null;
if (template != null) return defaults(responses, ChatColor.GREEN+"Updatable", ChatColor.RED+"Not Updatable") [((template.canUpdate())?0:1)];
else return null;
}
case "host.servers":
case "host.subservers": {
return Integer.toString(host.getSubServers().size());
}
case "host.players": {
return Integer.toString(host.getRemotePlayers().size());
}
case "host.subdata": {
return defaults(responses, ChatColor.GREEN+"Connected", ChatColor.YELLOW+"Unsupported", ChatColor.RED+"Disconnected") [(host.getSubData().length <= 0)?1:((host.getSubData()[0] == null)?2:0)];
}
case "host.subdata.channels":
case "host.subdata.subchannels": {
return Integer.toString(Math.max(host.getSubData().length - ((method.endsWith(".subchannels"))?1:0), 0));
}
case "host.signature": {
return host.getSignature();
}
case "group":
case "groups": {
return Integer.toString(cache.getGroups().size());
}
case "group.servers": {
return Integer.toString((group == null)?0:group.value().size());
}
case "group.players": {
int i = 0;
if (group != null) for (Server s : group.value()) i += s.getRemotePlayers().size();
return Integer.toString(i);
}
case "server":
case "servers": {
return Integer.toString(cache.getServers().size());
}
case "server.displayname":
case "subserver.displayname": {
return server.getDisplayName();
}
case "server.type":
case "subserver.type": {
return defaults(responses, "Subserver", "Server") [((server instanceof SubServer)?0:1)];
}
case "server.groups":
case "subserver.groups": {
return Integer.toString(server.getGroups().size());
}
case "server.address":
case "subserver.address": {
return server.getAddress().getAddress().getHostAddress() + ':' + server.getAddress().getPort();
}
case "server.motd":
case "subserver.motd": {
return server.getMotd();
}
case "server.restricted":
case "subserver.restricted": {
return defaults(responses, ChatColor.GREEN+"Public", ChatColor.RED+"Private") [(server.isRestricted())?1:0];
}
case "server.hidden":
case "subserver.hidden": {
return defaults(responses, ChatColor.GREEN+"Visible", ChatColor.RED+"Hidden") [(server.isHidden())?1:0];
}
case "server.players":
case "subserver.players": {
return Integer.toString(server.getRemotePlayers().size());
}
case "server.subdata":
case "subserver.subdata": {
return defaults(responses, ChatColor.GREEN+"Connected", ChatColor.RED+"Disconnected") [(server.getSubData()[0] == null)?1:0];
}
case "server.subdata.channels":
case "subserver.subdata.channels":
case "server.subdata.subchannels":
case "subserver.subdata.subchannels": {
return Integer.toString(server.getSubData().length - ((method.endsWith(".subchannels"))?1:0));
}
case "server.signature":
case "subserver.signature": {
return server.getSignature();
}
case "subserver":
case "subservers": {
return Integer.toString(cache.getSubServers().size());
}
case "subserver.available": {
return defaults(responses, ChatColor.GREEN+"Available", ChatColor.RED+"Unavailable") [(subserver.isAvailable())?0:1];
}
case "subserver.enabled": {
return defaults(responses, ChatColor.GREEN+"Enabled", ChatColor.RED+"Disabled") [(subserver.isEnabled())?0:1];
}
case "subserver.editable": {
return defaults(responses, ChatColor.GREEN+"Editable", ChatColor.RED+"Locked") [(subserver.isEditable())?0:1];
}
case "subserver.running": {
return defaults(responses, ChatColor.GREEN+"Running", ChatColor.RED+"Offline") [(subserver.isRunning())?0:1];
}
case "subserver.online": {
return defaults(responses, ChatColor.GREEN+"Online", ChatColor.YELLOW+"Starting", ChatColor.RED+"Offline") [(subserver.isOnline())?0:((subserver.isRunning())?1:2)];
}
case "subserver.logging": {
return defaults(responses, ChatColor.GREEN+"Logging", ChatColor.RED+"Muted") [(subserver.isLogging())?0:1];
}
case "subserver.temporary": {
return defaults(responses, ChatColor.GREEN+"Permanent", ChatColor.AQUA+"Temporary") [
(subserver.getStopAction() == SubServer.StopAction.REMOVE_SERVER || subserver.getStopAction() == SubServer.StopAction.RECYCLE_SERVER || subserver.getStopAction() == SubServer.StopAction.DELETE_SERVER)?1:0
];
}
case "subserver.stopaction": {
return subserver.getStopAction().toString();
}
case "subserver.incompatibilities":
case "subserver.incompatibilities.current": {
List<String> list = (method.endsWith(".current"))?subserver.getCurrentIncompatibilities():subserver.getIncompatibilities();
return Integer.toString(list.size());
}
default: {
return null;
}
}
}
private static String[] defaults(String[] overrides, String... defaults) {
for (int i = 0; i < defaults.length; ++i) {
defaults[i] = (((i < overrides.length && overrides[i].length() > 0)?overrides:defaults)[i]);
}
return defaults;
}
private final class Cache {
private HashMap<String, Proxy> proxies = new HashMap<String, Proxy>();
private HashMap<String, Host> hosts = new HashMap<String, Host>();
private HashMap<String, Server> servers = new HashMap<String, Server>();
private Proxy master = null;
private Listener events = new Events();
private void reset() {
proxies.clear();
hosts.clear();
servers.clear();
master = null;
}
private void refresh() {
if (SubAPI.getInstance().getSubDataNetwork()[0] != null) {
SubAPI.getInstance().getProxies(proxies -> {
this.proxies = new HashMap<>(proxies);
});
SubAPI.getInstance().getMasterProxy(master -> {
this.master = master;
});
SubAPI.getInstance().getHosts(hosts -> {
this.hosts = new HashMap<>(hosts);
});
SubAPI.getInstance().getServers(servers -> {
this.servers = new HashMap<>(servers);
});
}
}
private final class Events implements Listener {
private HashMap<String, BukkitTask> edits = new HashMap<String, BukkitTask>();
@EventHandler
public void add(SubAddProxyEvent e) {
SubAPI.getInstance().getProxy(e.getProxy(), proxy -> {
if (proxy != null) proxies.put(proxy.getName().toLowerCase(), proxy);
});
}
@EventHandler
public void add(SubAddHostEvent e) {
SubAPI.getInstance().getHost(e.getHost(), host -> {
if (host != null) hosts.put(host.getName().toLowerCase(), host);
});
}
@EventHandler
public void add(SubAddServerEvent e) {
add(e.getServer());
}
public void add(String s) {
SubAPI.getInstance().getServer(s, server -> {
if (server != null) servers.put(server.getName().toLowerCase(), server);
});
}
@EventHandler
public void edit(SubEditServerEvent e) {
String s = e.getServer().toLowerCase();
if (edits.keySet().contains(s)) edits.get(s).cancel();
edits.put(s, Bukkit.getScheduler().runTaskLater(plugin, () -> add(s), 120L));
}
@EventHandler
public void start(SubStartEvent e) {
Server server = getServer(e.getServer());
if (server != null) {
Try.all.run(() -> Util.<ObjectMap<String>>reflect(Server.class.getDeclaredField("raw"), server).set("running", true));
add(e.getServer());
}
}
@EventHandler
public void started(SubStartedEvent e) {
Server server = getServer(e.getServer());
if (server != null) {
Try.all.run(() -> Util.<ObjectMap<String>>reflect(Server.class.getDeclaredField("raw"), server).set("online", true));
add(e.getServer());
}
}
@EventHandler
public void stopped(SubStoppedEvent e) {
Server server = getServer(e.getServer());
if (server != null) Try.all.run(() -> {
ObjectMap<String> raw = Util.reflect(Server.class.getDeclaredField("raw"), server);
raw.set("online", false);
raw.set("running", false);
add(e.getServer());
});
}
}
public Map<String, Proxy> getProxies() {
return proxies;
}
public Proxy getProxy(String name) {
Util.nullpo(name);
Proxy proxy = getProxies().getOrDefault(name.toLowerCase(), null);
if (proxy == null && master != null && master.getName().equalsIgnoreCase(name)) proxy = master;
return proxy;
}
public Proxy getMasterProxy() {
return master;
}
private Map<String, Host> getHosts() {
return hosts;
}
private Host getHost(String name) {
Util.nullpo(name);
return getHosts().get(name.toLowerCase());
}
public Map<String, List<Server>> getGroups() {
TreeMap<String, List<Server>> groups = new TreeMap<String, List<Server>>();
HashMap<String, String> conflitresolver = new HashMap<String, String>();
for (Server server : getServers().values()) {
for (String name : server.getGroups()) {
String group = name;
if (conflitresolver.keySet().contains(name.toLowerCase())) {
group = conflitresolver.get(name.toLowerCase());
} else {
conflitresolver.put(name.toLowerCase(), name);
}
List<Server> list = (groups.keySet().contains(group))?groups.get(group):new ArrayList<Server>();
list.add(server);
groups.put(group, list);
}
}
return groups;
}
public Map<String, List<Server>> getLowercaseGroups() {
Map<String, List<Server>> groups = getGroups();
TreeMap<String, List<Server>> lowercaseGroups = new TreeMap<String, List<Server>>();
for (String key : groups.keySet()) {
lowercaseGroups.put(key.toLowerCase(), groups.get(key));
}
return lowercaseGroups;
}
public Pair<String, List<Server>> getGroup(String name) {
Util.nullpo(name);
for (Map.Entry<String, List<Server>> group : getLowercaseGroups().entrySet()) {
if (group.getKey().equalsIgnoreCase(name)) return new ContainedPair<>(group.getKey(), group.getValue());
}
return null;
}
public Map<String, Server> getServers() {
return servers;
}
public Server getServer(String name) {
Util.nullpo(name);
return getServers().get(name.toLowerCase());
}
public Map<String, SubServer> getSubServers() {
TreeMap<String, SubServer> servers = new TreeMap<String, SubServer>();
for (Map.Entry<String, Server> server : this.servers.entrySet()) {
if (server.getValue() instanceof SubServer) servers.put(server.getKey(), (SubServer) server.getValue());
}
return servers;
}
public SubServer getSubServer(String name) {
Util.nullpo(name);
return getSubServers().get(name.toLowerCase());
}
return plugin.phi.request(player, request);
}
}

View File

@ -1,5 +1,8 @@
package net.ME1312.SubServers.Client.Bukkit.Library;
import net.ME1312.SubServers.Client.Bukkit.Library.Compatibility.AgnosticScheduler;
import net.ME1312.SubServers.Client.Bukkit.SubAPI;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
@ -23,6 +26,9 @@ import java.util.logging.Level;
import java.util.stream.Collectors;
import java.util.zip.GZIPOutputStream;
/**
* SubServers BStats Metrics Implementation
*/
public class Metrics {
private final Plugin plugin;
@ -77,7 +83,7 @@ public class Metrics {
enabled,
this::appendPlatformData,
this::appendServiceData,
submitDataTask -> Bukkit.getScheduler().runTask(plugin, submitDataTask),
submitDataTask -> AgnosticScheduler.global.runs(plugin, c -> submitDataTask.run()),
plugin::isEnabled,
(message, error) -> this.plugin.getLogger().log(Level.WARNING, message, error),
(message) -> this.plugin.getLogger().log(Level.INFO, message),
@ -86,13 +92,21 @@ public class Metrics {
logResponseStatusText);
}
/**
* Add subservers platform information as custom charts
*/
public Metrics addPlatformCharts() {
return addCustomChart(new SimplePie("subservers_version", () -> SubAPI.getInstance().getPluginVersion().toString()));
}
/**
* Adds a custom chart.
*
* @param chart The chart to add.
*/
public void addCustomChart(CustomChart chart) {
public Metrics addCustomChart(CustomChart chart) {
metricsBase.addCustomChart(chart);
return this;
}
private void appendPlatformData(JsonObjectBuilder builder) {
@ -129,7 +143,7 @@ public class Metrics {
public static class MetricsBase {
/** The version of the Metrics class. */
public static final String METRICS_VERSION = "2.2.1";
public static final String METRICS_VERSION = "3.0.0";
private static final ScheduledExecutorService scheduler =
Executors.newScheduledThreadPool(1, task -> new Thread(task, "bStats-Metrics"));
@ -214,6 +228,7 @@ public class Metrics {
this.logResponseStatusText = logResponseStatusText;
checkRelocation();
if (enabled) {
// WARNING: Removing the option to opt-out will get your plugin banned from bStats
startSubmitting();
}
}
@ -350,9 +365,9 @@ public class Metrics {
}
}
public static class AdvancedBarChart extends CustomChart {
public static class DrilldownPie extends CustomChart {
private final Callable<Map<String, int[]>> callable;
private final Callable<Map<String, Map<String, Integer>>> callable;
/**
* Class constructor.
@ -360,99 +375,33 @@ public class Metrics {
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public AdvancedBarChart(String chartId, Callable<Map<String, int[]>> callable) {
public DrilldownPie(String chartId, Callable<Map<String, Map<String, Integer>>> callable) {
super(chartId);
this.callable = callable;
}
@Override
protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
public JsonObjectBuilder.JsonObject getChartData() throws Exception {
JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
Map<String, int[]> map = callable.call();
Map<String, Map<String, Integer>> map = callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
return null;
}
boolean allSkipped = true;
for (Map.Entry<String, int[]> entry : map.entrySet()) {
if (entry.getValue().length == 0) {
// Skip this invalid
continue;
boolean reallyAllSkipped = true;
for (Map.Entry<String, Map<String, Integer>> entryValues : map.entrySet()) {
JsonObjectBuilder valueBuilder = new JsonObjectBuilder();
boolean allSkipped = true;
for (Map.Entry<String, Integer> valueEntry : map.get(entryValues.getKey()).entrySet()) {
valueBuilder.appendField(valueEntry.getKey(), valueEntry.getValue());
allSkipped = false;
}
allSkipped = false;
valuesBuilder.appendField(entry.getKey(), entry.getValue());
}
if (allSkipped) {
// Null = skip the chart
return null;
}
return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build();
}
}
public static class SimpleBarChart extends CustomChart {
private final Callable<Map<String, Integer>> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public SimpleBarChart(String chartId, Callable<Map<String, Integer>> callable) {
super(chartId);
this.callable = callable;
}
@Override
protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
Map<String, Integer> map = callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
return null;
}
for (Map.Entry<String, Integer> entry : map.entrySet()) {
valuesBuilder.appendField(entry.getKey(), new int[] {entry.getValue()});
}
return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build();
}
}
public static class MultiLineChart extends CustomChart {
private final Callable<Map<String, Integer>> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public MultiLineChart(String chartId, Callable<Map<String, Integer>> callable) {
super(chartId);
this.callable = callable;
}
@Override
protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
Map<String, Integer> map = callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
return null;
}
boolean allSkipped = true;
for (Map.Entry<String, Integer> entry : map.entrySet()) {
if (entry.getValue() == 0) {
// Skip this invalid
continue;
if (!allSkipped) {
reallyAllSkipped = false;
valuesBuilder.appendField(entryValues.getKey(), valueBuilder.build());
}
allSkipped = false;
valuesBuilder.appendField(entry.getKey(), entry.getValue());
}
if (allSkipped) {
if (reallyAllSkipped) {
// Null = skip the chart
return null;
}
@ -500,6 +449,76 @@ public class Metrics {
}
}
public static class MultiLineChart extends CustomChart {
private final Callable<Map<String, Integer>> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public MultiLineChart(String chartId, Callable<Map<String, Integer>> callable) {
super(chartId);
this.callable = callable;
}
@Override
protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
Map<String, Integer> map = callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
return null;
}
boolean allSkipped = true;
for (Map.Entry<String, Integer> entry : map.entrySet()) {
if (entry.getValue() == 0) {
// Skip this invalid
continue;
}
allSkipped = false;
valuesBuilder.appendField(entry.getKey(), entry.getValue());
}
if (allSkipped) {
// Null = skip the chart
return null;
}
return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build();
}
}
public static class SimpleBarChart extends CustomChart {
private final Callable<Map<String, Integer>> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public SimpleBarChart(String chartId, Callable<Map<String, Integer>> callable) {
super(chartId);
this.callable = callable;
}
@Override
protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
Map<String, Integer> map = callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
return null;
}
for (Map.Entry<String, Integer> entry : map.entrySet()) {
valuesBuilder.appendField(entry.getKey(), new int[] {entry.getValue()});
}
return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build();
}
}
public abstract static class CustomChart {
private final String chartId;
@ -534,32 +553,6 @@ public class Metrics {
protected abstract JsonObjectBuilder.JsonObject getChartData() throws Exception;
}
public static class SingleLineChart extends CustomChart {
private final Callable<Integer> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public SingleLineChart(String chartId, Callable<Integer> callable) {
super(chartId);
this.callable = callable;
}
@Override
protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
int value = callable.call();
if (value == 0) {
// Null = skip the chart
return null;
}
return new JsonObjectBuilder().appendField("value", value).build();
}
}
public static class SimplePie extends CustomChart {
private final Callable<String> callable;
@ -586,9 +579,9 @@ public class Metrics {
}
}
public static class DrilldownPie extends CustomChart {
public static class AdvancedBarChart extends CustomChart {
private final Callable<Map<String, Map<String, Integer>>> callable;
private final Callable<Map<String, int[]>> callable;
/**
* Class constructor.
@ -596,33 +589,29 @@ public class Metrics {
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public DrilldownPie(String chartId, Callable<Map<String, Map<String, Integer>>> callable) {
public AdvancedBarChart(String chartId, Callable<Map<String, int[]>> callable) {
super(chartId);
this.callable = callable;
}
@Override
public JsonObjectBuilder.JsonObject getChartData() throws Exception {
protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
Map<String, Map<String, Integer>> map = callable.call();
Map<String, int[]> map = callable.call();
if (map == null || map.isEmpty()) {
// Null = skip the chart
return null;
}
boolean reallyAllSkipped = true;
for (Map.Entry<String, Map<String, Integer>> entryValues : map.entrySet()) {
JsonObjectBuilder valueBuilder = new JsonObjectBuilder();
boolean allSkipped = true;
for (Map.Entry<String, Integer> valueEntry : map.get(entryValues.getKey()).entrySet()) {
valueBuilder.appendField(valueEntry.getKey(), valueEntry.getValue());
allSkipped = false;
}
if (!allSkipped) {
reallyAllSkipped = false;
valuesBuilder.appendField(entryValues.getKey(), valueBuilder.build());
boolean allSkipped = true;
for (Map.Entry<String, int[]> entry : map.entrySet()) {
if (entry.getValue().length == 0) {
// Skip this invalid
continue;
}
allSkipped = false;
valuesBuilder.appendField(entry.getKey(), entry.getValue());
}
if (reallyAllSkipped) {
if (allSkipped) {
// Null = skip the chart
return null;
}
@ -630,6 +619,32 @@ public class Metrics {
}
}
public static class SingleLineChart extends CustomChart {
private final Callable<Integer> callable;
/**
* Class constructor.
*
* @param chartId The id of the chart.
* @param callable The callable which is used to request the chart data.
*/
public SingleLineChart(String chartId, Callable<Integer> callable) {
super(chartId);
this.callable = callable;
}
@Override
protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
int value = callable.call();
if (value == 0) {
// Null = skip the chart
return null;
}
return new JsonObjectBuilder().appendField("value", value).build();
}
}
/**
* An extremely simple JSON builder.
*

View File

@ -0,0 +1,810 @@
package net.ME1312.SubServers.Client.Bukkit.Library;
import net.ME1312.Galaxi.Library.Container.ContainedPair;
import net.ME1312.Galaxi.Library.Container.Container;
import net.ME1312.Galaxi.Library.Container.Pair;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.Galaxi.Library.Merger;
import net.ME1312.Galaxi.Library.Try;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubServers.Client.Bukkit.Event.*;
import net.ME1312.SubServers.Client.Bukkit.Library.Compatibility.AgnosticScheduler;
import net.ME1312.SubServers.Client.Bukkit.SubAPI;
import net.ME1312.SubServers.Client.Bukkit.SubPlugin;
import net.ME1312.SubServers.Client.Common.Network.API.*;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.OfflinePlayer;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Placeholder Executor Class
*/
public final class Placeholders {
private final CopyOnWriteArrayList<Runnable> listeners;
private final SubPlugin plugin;
public final Cache cache;
private MethodHandle papi;
private Runnable task;
private boolean init;
/**
* Create a Placeholder Executor Instance
*
* @param plugin SubPlugin
*/
public Placeholders(SubPlugin plugin) {
this.plugin = plugin;
this.listeners = new CopyOnWriteArrayList<>();
this.cache = new Cache();
this.init = false;
}
public void start() {
if (!init) {
init = true;
papi = Try.all.get(() -> MethodHandles.publicLookup().findStatic(Class.forName("me.clip.placeholderapi.PlaceholderAPI"), "setPlaceholders", MethodType.methodType(String.class, new Class[]{ OfflinePlayer.class, String.class })));
Bukkit.getPluginManager().registerEvents(cache.events, plugin);
AgnosticScheduler.async.runs(plugin, c -> {
if (task == null) {
int interval = plugin.config.get().getMap("Settings").getInt("PlaceholderAPI-Cache-Interval", 30);
int start = interval - new Random().nextInt(interval + 1); // Don't have all servers request at the same time
Consumer<Runnable> task = c2 -> cache.refresh(() -> {
for (Runnable listener : listeners) {
try {
listener.run();
} catch (Throwable e) {
e.printStackTrace();
}
}
});
this.task = AgnosticScheduler.async.repeats(plugin, task, start, interval, TimeUnit.SECONDS);
task.accept(null);
}
}, 6, TimeUnit.SECONDS);
}
}
public void stop() {
if (task != null) {
try {
task.run();
} catch (Throwable exception) {}
task = null;
}
}
public void clear() {
cache.reset();
}
public void listen(Runnable task) {
listeners.add(task);
}
public String request(OfflinePlayer player, String request) {
boolean colored = !request.startsWith("plain_");
if (!colored || request.startsWith("color_")) request = request.substring(6);
if (!init) start();
String response = runMethod(player, request);
if (response != null && !colored) {
return ChatColor.stripColor(response);
} else {
return response;
}
}
private static final Pattern replacements = Pattern.compile("#?([^\\s#]+?\\(.*?\\))|\\$([^$]+)\\$", Pattern.CASE_INSENSITIVE);
private String[] arguments(OfflinePlayer player, String text, boolean replace) {
LinkedList<String> arguments = new LinkedList<>();
if (text != null && !text.isEmpty()) {
Pattern p = replacements;
Matcher m = p.matcher(text);
StringBuilder argument = new StringBuilder();
while (m.find()) {
String[] replacement = findMethod(player, text, m.start(), replace);
if (replacement[0].contains(",")) {
String[] s = replacement[0].split(",");
argument.append(s[0]);
arguments.add(argument.toString().trim());
for (int i = 1; i < s.length - 1; ++i) {
arguments.add(s[i].trim());
}
argument = new StringBuilder();
argument.append(s[s.length - 1]);
} else {
argument.append(replacement[0]);
}
argument.append(replacement[1]);
text = replacement[2];
m = p.matcher(text);
}
if (text.contains(",")) {
String[] s = text.split(",");
argument.append(s[0]);
arguments.add(argument.toString().trim());
argument = null;
for (int i = 1; i < s.length; ++i) {
arguments.add(s[i].trim());
}
} else if (text.length() > 0) {
argument.append(text);
}
if (argument != null && argument.length() > 0) {
arguments.add(argument.toString().trim());
}
}
return arguments.toArray(new String[0]);
}
public String replace(OfflinePlayer player, String text) {
if (text != null) {
Pattern p = replacements;
Matcher m = p.matcher(text);
StringBuilder str = new StringBuilder();
while (m.find()) {
String[] replacement = findMethod(player, text, m.start(), true);
str.append(replacement[0]);
str.append(replacement[1]);
text = replacement[2];
m = p.matcher(text);
}
str.append(text);
return str.toString();
} else {
return null;
}
}
private String[] findMethod(OfflinePlayer player, String text, int start, boolean run) {
String[] values = new String[3];
values[0] = text.substring(0, start);
text = text.substring(start);
int[] open = {'(', '<'};
int[] close = {')', '>'};
Arrays.sort(open);
Arrays.sort(close);
int i = -1;
if (text.codePointAt(0) == '$') {
Matcher m = Pattern.compile("^\\$([^$]+)\\$", Pattern.CASE_INSENSITIVE).matcher(text);
if (m.find()) {
String str = '%' + m.group(1) + '%';
text = text.substring(m.end());
if (run) {
String response = (papi == null)?null:Try.all.get(() -> (String) papi.invokeExact(player, str));
values[1] = (response == null)?m.group():response;
} else {
values[1] = m.group();
}
}
} else {
++i;
boolean responses = false;
StringBuilder str = new StringBuilder();
for (int level = 0; i < text.codePoints().count(); ++i) {
int c = text.codePointAt(i);
str.appendCodePoint(c);
if (Arrays.binarySearch(open, c) >= 0) {
++level;
} else if (Arrays.binarySearch(close, c) >= 0) {
--level;
if (level <= 0) {
if (responses) break;
boolean more = false;
for (int ix = i + 1; ix < text.codePoints().count(); ++ix) {
int cx = text.codePointAt(ix);
if (!Character.isWhitespace(cx) && cx != '_') {
more = cx == '<';
break;
}
}
if (!more) break;
else responses = true;
}
}
}
if (run) {
String response = runMethod(player, str.toString());
values[1] = (response == null)?str.toString():response;
} else {
values[1] = str.toString();
}
}
StringBuilder str = new StringBuilder();
for (i += 1; i < text.codePoints().count(); ++i) {
str.appendCodePoint(text.codePointAt(i));
}
values[2] = str.toString();
return values;
}
private String[] parseMethod(OfflinePlayer player, String text) {
Matcher m = Pattern.compile("^#?(.+?)(?:[\\s_]*\\((.*?)\\))?(?:[\\s_]*<(.*)>)?$", Pattern.CASE_INSENSITIVE).matcher(text);
if (m.find()) {
String[] values = new String[3];
values[0] = m.group(1);
if (m.group(2) == null || m.group(2).trim().isEmpty() ||
m.group(3) == null || m.group(3).trim().isEmpty()) {
// Simple parsing: () or <>
values[1] = m.group(2);
values[2] = m.group(3);
} else {
// Complex parsing: () and <>
text = text.substring(m.end(1));
int stage = 1, level = 0, i = 0;
char open = '(', close = ')';
boolean responses = false;
StringBuilder str = new StringBuilder();
for (; i < text.codePoints().count(); ++i) {
int c = text.codePointAt(i);
if (c == open) {
if (level > 0) str.appendCodePoint(c);
++level;
} else if (c == close) {
--level;
if (level > 0) str.appendCodePoint(c);
else {
if (responses) break;
boolean more = false;
for (int ix = i + 1; ix < text.codePoints().count(); ++ix) {
int cx = text.codePointAt(ix);
if (!Character.isWhitespace(cx) && cx != '_') {
more = cx == '<';
break;
}
}
if (!more) break;
else {
responses = true;
open = '<'; close = '>';
values[stage++] = str.toString();
str = new StringBuilder();
}
}
} else {
if (level > 0) str.appendCodePoint(c);
}
}
values[stage] = str.toString();
if (level > 0 || ++i < text.codePoints().count()) {
return null;
}
}
return values;
} else {
return null;
}
}
private String runMethod(OfflinePlayer player, String text) {
String[] parsed = parseMethod(player, text);
if (parsed != null) {
String method = parsed[0];
String[] args = arguments(player, parsed[1], true);
String[] responses = arguments(player, parsed[2], false);
for (int i = 0; i < responses.length; ++i)
responses[i] = ChatColor.translateAlternateColorCodes('&', responses[i].trim());
return replace(player, runMethod(player, method, args, responses));
} else {
return null;
}
}
@SuppressWarnings("ConstantConditions")
private String runMethod(OfflinePlayer player, String method, String[] args, String[] responses) {
Server server = (plugin.api.getName() != null)? cache.getServer(plugin.api.getName()) : null;
SubServer subserver = (server instanceof SubServer)? (SubServer) server : null;
Pair<String, List<Server>> group = null;
Host host = (subserver != null)? cache.getHost(subserver.getHost()) : null;
Proxy proxy = cache.getMasterProxy();
method = method.toLowerCase();
if (method.startsWith("proxy.")) {
if (args.length > 0 && !args[0].isEmpty()) proxy = cache.getProxy(args[0]);
if (proxy == null) return null;
} else if (method.startsWith("host.")) {
if (args.length > 0 && !args[0].isEmpty()) host = cache.getHost(args[0]);
if (host == null) return null;
} else if (method.startsWith("group.")) {
if (args.length > 0 && !args[0].isEmpty()) group = cache.getGroup(args[0]);
// if (group == null) return null; // Empty groups are null
} else if (method.startsWith("server.")) {
if (args.length > 0 && !args[0].isEmpty()) server = cache.getServer(args[0]);
if (server == null) return null;
} else if (method.startsWith("subserver.")) {
if (args.length > 0 && !args[0].isEmpty()) server = subserver = cache.getSubServer(args[0]);
if (subserver == null) return null;
}
// --- Methods where Objects link to other Objects --
if (method.startsWith("subserver.host")) {
if (method.equals("subserver.host")) {
return subserver.getHost();
} else {
LinkedList<String> arguments = new LinkedList<String>();
arguments.addAll(Arrays.asList(args));
if (args.length > 0) arguments.removeFirst();
arguments.addFirst(subserver.getHost());
return runMethod(player, method.substring(10), arguments.toArray(new String[0]), responses);
}
} else if (method.startsWith("subserver.template")) {
if (method.equals("subserver.template")) {
return (subserver.getTemplate() != null)?subserver.getTemplate():defaults(responses, "(custom)")[0];
} else if (subserver.getTemplate() != null) {
LinkedList<String> arguments = new LinkedList<String>();
arguments.addAll(Arrays.asList(args));
if (args.length > 0) arguments.removeFirst();
arguments.addFirst(subserver.getTemplate());
arguments.addFirst(subserver.getHost());
return runMethod(player, "host.creator." + method.substring(10), arguments.toArray(new String[0]), responses);
} else {
return null;
}
} else switch (method) { // --- Straight up Methods ---
case "example": {
return defaults(responses, ChatColor.LIGHT_PURPLE+"Example!")[0];
}
case "players": {
int i = cache.getMasterProxy().getPlayers().size();
for (Proxy p : cache.getProxies().values()) i += p.getPlayers().size();
return Integer.toString(i);
}
case "proxy":
case "proxies": {
return Integer.toString(cache.getProxies().size() + 1);
}
case "proxy.displayname": {
return proxy.getDisplayName();
}
case "proxy.type": {
return defaults(responses, "Master Proxy", "Proxy") [((proxy.isMaster())?0:1)];
}
case "proxy.players": {
return Integer.toString(proxy.getPlayers().size());
}
case "proxy.subdata": {
return defaults(responses, ChatColor.GREEN+"Connected", ChatColor.RED+"Disconnected") [(proxy.getSubData()[0] == null)?1:0];
}
case "proxy.subdata.channels":
case "proxy.subdata.subchannels": {
return Integer.toString(proxy.getSubData().length - ((method.endsWith(".subchannels"))?1:0));
}
case "proxy.signature": {
return proxy.getSignature();
}
case "host":
case "hosts": {
return Integer.toString(cache.getHosts().size());
}
case "host.displayname": {
return host.getDisplayName();
}
case "host.available": {
return defaults(responses, ChatColor.GREEN+"Available", ChatColor.RED+"Unavailable") [(host.isAvailable())?0:1];
}
case "host.enabled": {
return defaults(responses, ChatColor.GREEN+"Enabled", ChatColor.RED+"Disabled") [(host.isEnabled())?0:1];
}
case "host.address": {
return host.getAddress().getHostAddress();
}
case "host.creator.template":
case "host.subcreator.template":
case "host.creator.templates":
case "host.subcreator.templates": {
return Integer.toString(host.getCreator().getTemplates().size());
}
case "host.creator.template.displayname":
case "host.subcreator.template.displayname": {
SubCreator.ServerTemplate template = (args.length > 1 && !args[1].isEmpty())? host.getCreator().getTemplate(args[1]) : null;
if (template != null) return template.getDisplayName();
else return null;
}
case "host.creator.template.enabled":
case "host.subcreator.template.enabled": {
SubCreator.ServerTemplate template = (args.length > 1 && !args[1].isEmpty())? host.getCreator().getTemplate(args[1]) : null;
if (template != null) return defaults(responses, ChatColor.GREEN+"Enabled", ChatColor.RED+"Disabled") [((template.isEnabled())?0:1)];
else return null;
}
case "host.creator.template.type":
case "host.subcreator.template.type": {
SubCreator.ServerTemplate template = (args.length > 1 && !args[1].isEmpty())? host.getCreator().getTemplate(args[1]) : null;
if (template != null) return template.getType().toString();
else return null;
}
case "host.creator.template.requiresversion":
case "host.subcreator.template.requiresversion": {
SubCreator.ServerTemplate template = (args.length > 1 && !args[1].isEmpty())? host.getCreator().getTemplate(args[1]) : null;
if (template != null) return defaults(responses, ChatColor.GREEN+"Optional", ChatColor.YELLOW+"Required") [((template.requiresVersion())?1:0)];
else return null;
}
case "host.creator.template.updatable":
case "host.subcreator.template.updatable": {
SubCreator.ServerTemplate template = (args.length > 1 && !args[1].isEmpty())? host.getCreator().getTemplate(args[1]) : null;
if (template != null) return defaults(responses, ChatColor.GREEN+"Updatable", ChatColor.RED+"Not Updatable") [((template.canUpdate())?0:1)];
else return null;
}
case "host.servers":
case "host.subservers": {
return Integer.toString(host.getSubServers().size());
}
case "host.players": {
return Integer.toString(host.getRemotePlayers().size());
}
case "host.subdata": {
return defaults(responses, ChatColor.GREEN+"Connected", ChatColor.YELLOW+"Unsupported", ChatColor.RED+"Disconnected") [(host.getSubData().length <= 0)?1:((host.getSubData()[0] == null)?2:0)];
}
case "host.subdata.channels":
case "host.subdata.subchannels": {
return Integer.toString(Math.max(host.getSubData().length - ((method.endsWith(".subchannels"))?1:0), 0));
}
case "host.signature": {
return host.getSignature();
}
case "group":
case "groups": {
return Integer.toString(cache.getGroups().size());
}
case "group.servers": {
return Integer.toString((group == null)?0:group.value().size());
}
case "group.players": {
int i = 0;
if (group != null) for (Server s : group.value()) i += s.getRemotePlayers().size();
return Integer.toString(i);
}
case "server":
case "servers": {
return Integer.toString(cache.getServers().size());
}
case "server.displayname":
case "subserver.displayname": {
return server.getDisplayName();
}
case "server.type":
case "subserver.type": {
return defaults(responses, "Subserver", "Server") [((server instanceof SubServer)?0:1)];
}
case "server.groups":
case "subserver.groups": {
return Integer.toString(server.getGroups().size());
}
case "server.address":
case "subserver.address": {
return server.getAddress().getAddress().getHostAddress() + ':' + server.getAddress().getPort();
}
case "server.motd":
case "subserver.motd": {
return server.getMotd();
}
case "server.restricted":
case "subserver.restricted": {
return defaults(responses, ChatColor.GREEN+"Public", ChatColor.RED+"Private") [(server.isRestricted())?1:0];
}
case "server.hidden":
case "subserver.hidden": {
return defaults(responses, ChatColor.GREEN+"Visible", ChatColor.RED+"Hidden") [(server.isHidden())?1:0];
}
case "server.players":
case "subserver.players": {
return Integer.toString(server.getRemotePlayers().size());
}
case "server.subdata":
case "subserver.subdata": {
return defaults(responses, ChatColor.GREEN+"Connected", ChatColor.RED+"Disconnected") [(server.getSubData()[0] == null)?1:0];
}
case "server.subdata.channels":
case "subserver.subdata.channels":
case "server.subdata.subchannels":
case "subserver.subdata.subchannels": {
return Integer.toString(server.getSubData().length - ((method.endsWith(".subchannels"))?1:0));
}
case "server.signature":
case "subserver.signature": {
return server.getSignature();
}
case "subserver":
case "subservers": {
return Integer.toString(cache.getSubServers().size());
}
case "subserver.available": {
return defaults(responses, ChatColor.GREEN+"Available", ChatColor.RED+"Unavailable") [(subserver.isAvailable())?0:1];
}
case "subserver.enabled": {
return defaults(responses, ChatColor.GREEN+"Enabled", ChatColor.RED+"Disabled") [(subserver.isEnabled())?0:1];
}
case "subserver.editable": {
return defaults(responses, ChatColor.GREEN+"Editable", ChatColor.RED+"Locked") [(subserver.isEditable())?0:1];
}
case "subserver.running": {
return defaults(responses, ChatColor.GREEN+"Running", ChatColor.RED+"Offline") [(subserver.isRunning())?0:1];
}
case "subserver.online": {
return defaults(responses, ChatColor.GREEN+"Online", ChatColor.YELLOW+"Starting", ChatColor.RED+"Offline") [(subserver.isOnline())?0:((subserver.isRunning())?1:2)];
}
case "subserver.logging": {
return defaults(responses, ChatColor.GREEN+"Logging", ChatColor.RED+"Muted") [(subserver.isLogging())?0:1];
}
case "subserver.temporary": {
return defaults(responses, ChatColor.GREEN+"Permanent", ChatColor.AQUA+"Temporary") [
(subserver.getStopAction() == SubServer.StopAction.REMOVE_SERVER || subserver.getStopAction() == SubServer.StopAction.RECYCLE_SERVER || subserver.getStopAction() == SubServer.StopAction.DELETE_SERVER)?1:0
];
}
case "subserver.stopaction": {
return subserver.getStopAction().toString();
}
case "subserver.incompatibilities":
case "subserver.incompatibilities.current": {
List<String> list = (method.endsWith(".current"))?subserver.getCurrentIncompatibilities():subserver.getIncompatibilities();
return Integer.toString(list.size());
}
default: {
return null;
}
}
}
private static String[] defaults(String[] overrides, String... defaults) {
for (int i = 0; i < defaults.length; ++i) {
defaults[i] = (((i < overrides.length && overrides[i].length() > 0)?overrides:defaults)[i]);
}
return defaults;
}
public final class Cache {
private Map<String, Proxy> proxies = new TreeMap<>();
private Map<String, Host> hosts = new TreeMap<>();
private Map<String, Server> servers = new TreeMap<>();
private Proxy master = null;
private Listener events = new Events();
private void reset() {
proxies.clear();
hosts.clear();
servers.clear();
master = null;
}
private void refresh(Runnable callback) {
if (SubAPI.getInstance().getSubDataNetwork()[0] != null) {
Container<Boolean> order = new Container<>(null);
Merger async = new Merger(() -> {
try {
Map<String, SubServer> servers;
for (Host host : hosts.values()) {
servers = Util.reflect(Host.class.getDeclaredField("servers"), host);
if (order.value) {
this.servers.putAll(servers);
} else {
servers.replaceAll((name, existing) -> {
Server server = this.servers.getOrDefault(name, null);
return (server instanceof SubServer)? (SubServer) server : existing;
});
}
}
} catch (Throwable e) {
e.printStackTrace();
}
callback.run();
});
async.reserve(4);
SubAPI.getInstance().getProxies(proxies -> {
this.proxies = proxies;
async.release();
});
SubAPI.getInstance().getMasterProxy(master -> {
this.master = master;
async.release();
});
SubAPI.getInstance().getHosts(hosts -> {
order.value = true;
this.hosts = hosts;
async.release();
});
SubAPI.getInstance().getServers(servers -> {
order.value = false;
this.servers = servers;
async.release();
});
}
}
private final class Events implements Listener {
private HashMap<String, Runnable> edits = new HashMap<String, Runnable>();
@EventHandler(priority = EventPriority.LOWEST)
public void add(SubAddProxyEvent e) {
SubAPI.getInstance().getProxy(e.getProxy(), proxy -> {
if (proxy != null) proxies.put(proxy.getName().toLowerCase(), proxy);
});
}
@EventHandler(priority = EventPriority.LOWEST)
public void add(SubAddHostEvent e) {
SubAPI.getInstance().getHost(e.getHost(), host -> {
if (host != null) hosts.put(host.getName().toLowerCase(), host);
});
}
@EventHandler(priority = EventPriority.LOWEST)
public void add(SubAddServerEvent e) {
add(e.getServer());
}
public void add(String s) {
SubAPI.getInstance().getServer(s, server -> {
if (server != null) servers.put(server.getName().toLowerCase(), server);
});
}
@EventHandler(priority = EventPriority.LOWEST)
public void edit(SubEditServerEvent e) {
String s = e.getServer().toLowerCase();
if (edits.containsKey(s)) edits.get(s).run();
edits.put(s, AgnosticScheduler.async.runs(plugin, servers.containsKey(s)? (c -> servers.get(s).refresh()) : (c -> add(s)), 6, TimeUnit.SECONDS));
}
@EventHandler(priority = EventPriority.LOWEST)
public void start(SubStartEvent e) {
Server server = getServer(e.getServer());
if (server != null) {
Try.all.run(() -> Util.<ObjectMap<String>>reflect(Server.class.getDeclaredField("raw"), server).set("running", true));
server.refresh();
} else add(e.getServer());
}
@EventHandler(priority = EventPriority.LOWEST)
public void started(SubStartedEvent e) {
Server server = getServer(e.getServer());
if (server != null) {
Try.all.run(() -> Util.<ObjectMap<String>>reflect(Server.class.getDeclaredField("raw"), server).set("online", true));
server.refresh();
} else add(e.getServer());
}
@EventHandler(priority = EventPriority.LOWEST)
public void stopping(SubStopEvent e) {
Server server = getServer(e.getServer());
if (server != null) {
Try.all.run(() -> Util.<ObjectMap<String>>reflect(Server.class.getDeclaredField("raw"), server).set("stopping", true));
server.refresh();
} else add(e.getServer());
}
@EventHandler(priority = EventPriority.LOWEST)
public void stopped(SubStoppedEvent e) {
Server server = getServer(e.getServer());
if (server != null) Try.all.run(() -> {
ObjectMap<String> raw = Util.reflect(Server.class.getDeclaredField("raw"), server);
raw.set("online", false);
raw.set("running", false);
raw.set("stopping", false);
server.refresh();
}); else add(e.getServer());
}
}
public Map<String, Proxy> getProxies() {
return proxies;
}
public Proxy getProxy(String name) {
Util.nullpo(name);
Proxy proxy = getProxies().getOrDefault(name.toLowerCase(), null);
if (proxy == null && master != null && master.getName().equalsIgnoreCase(name)) proxy = master;
return proxy;
}
public Proxy getMasterProxy() {
return master;
}
public Map<String, Host> getHosts() {
return hosts;
}
public Host getHost(String name) {
Util.nullpo(name);
return getHosts().getOrDefault(name.toLowerCase(), null);
}
public Map<String, List<Server>> getGroups() {
TreeMap<String, List<Server>> groups = new TreeMap<String, List<Server>>();
HashMap<String, String> conflitresolver = new HashMap<String, String>();
for (Server server : getServers().values()) {
for (String name : server.getGroups()) {
String group = name;
if (conflitresolver.containsKey(name.toLowerCase())) {
group = conflitresolver.get(name.toLowerCase());
} else {
conflitresolver.put(name.toLowerCase(), name);
}
List<Server> list = (groups.containsKey(group))?groups.get(group):new ArrayList<Server>();
list.add(server);
groups.put(group, list);
}
}
return groups;
}
public Map<String, List<Server>> getLowercaseGroups() {
Map<String, List<Server>> groups = getGroups();
TreeMap<String, List<Server>> lowercaseGroups = new TreeMap<String, List<Server>>();
for (String key : groups.keySet()) {
lowercaseGroups.put(key.toLowerCase(), groups.get(key));
}
return lowercaseGroups;
}
public Pair<String, List<Server>> getGroup(String name) {
Util.nullpo(name);
for (Map.Entry<String, List<Server>> group : getLowercaseGroups().entrySet()) {
if (group.getKey().equalsIgnoreCase(name)) return new ContainedPair<>(group.getKey(), group.getValue());
}
return null;
}
public Map<String, Server> getServers() {
return servers;
}
public Server getServer(String name) {
Util.nullpo(name);
return getServers().getOrDefault(name.toLowerCase(), null);
}
public Map<String, SubServer> getSubServers() {
TreeMap<String, SubServer> servers = new TreeMap<String, SubServer>();
for (Map.Entry<String, Server> server : this.servers.entrySet()) {
if (server.getValue() instanceof SubServer) servers.put(server.getKey(), (SubServer) server.getValue());
}
return servers;
}
public SubServer getSubServer(String name) {
Util.nullpo(name);
return getSubServers().getOrDefault(name.toLowerCase(), null);
}
}
}

View File

@ -0,0 +1,42 @@
package net.ME1312.SubServers.Client.Bukkit.Library;
import net.ME1312.SubServers.Client.Common.Network.API.Server;
import net.ME1312.SubServers.Client.Common.Network.API.SubServer;
public enum SignState {
UNKNOWN(0, "Signs.Text.Unknown"),
OFFLINE(1, "Signs.Text.Offline"),
STARTING(3, "Signs.Text.Starting"),
ONLINE(4, "Signs.Text.Online"),
STOPPING(2, "Signs.Text.Stopping"),
;
public final byte priority;
public final String text;
SignState(int priority, String text) {
this.priority = (byte) priority;
this.text = text;
}
public static SignState determine(SubServer server) {
if (!server.isRunning()) {
return SignState.OFFLINE;
} else if (server.isStopping()) {
return SignState.STOPPING;
} else if (server.isOnline()) {
return SignState.ONLINE;
} else {
return SignState.STARTING;
}
}
public static SignState determine(Server server) {
if (server instanceof SubServer) {
return determine((SubServer) server);
} else if (server.getSubData()[0] == null) {
return SignState.UNKNOWN;
} else {
return SignState.ONLINE;
}
}
}

View File

@ -49,7 +49,6 @@ public class PacketCheckPermissionResponse implements Forwardable, PacketObjectI
@Override
public void receive(SubDataSender client, ObjectMap<Integer> data) throws Throwable {
for (Consumer<Boolean> callback : callbacks.get(data.getUUID(0x0000))) callback.accept(data.getBoolean(0x0001));
callbacks.remove(data.getUUID(0x0000));
for (Consumer<Boolean> callback : callbacks.remove(data.getUUID(0x0000))) callback.accept(data.getBoolean(0x0001));
}
}

View File

@ -24,8 +24,7 @@ public class PacketDownloadLang implements PacketObjectIn<Integer>, PacketOut {
* @param plugin SubServers.Client
*/
public PacketDownloadLang(SubPlugin plugin) {
Util.nullpo(plugin);
this.plugin = plugin;
this.plugin = Util.nullpo(plugin);
}
/**

View File

@ -1,12 +1,15 @@
package net.ME1312.SubServers.Client.Bukkit.Network.Packet;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.Galaxi.Library.Util;
import net.ME1312.SubData.Client.Protocol.PacketObjectIn;
import net.ME1312.SubData.Client.Protocol.PacketObjectOut;
import net.ME1312.SubData.Client.SubDataSender;
import net.ME1312.SubServers.Client.Bukkit.Library.Compatibility.AgnosticScheduler;
import net.ME1312.SubServers.Client.Bukkit.SubPlugin;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.UUID;
@ -14,13 +17,18 @@ import java.util.UUID;
* Player Control Packet
*/
public class PacketExControlPlayer implements PacketObjectIn<Integer>, PacketObjectOut<Integer> {
private SubPlugin plugin;
private int response;
private UUID tracker;
/**
* New PacketExControlPlayer (In)
*
* @param plugin SubServers.Client
*/
public PacketExControlPlayer() {}
public PacketExControlPlayer(SubPlugin plugin) {
this.plugin = Util.nullpo(plugin);
}
/**
* New PacketExControlPlayer (Out)
@ -48,13 +56,18 @@ public class PacketExControlPlayer implements PacketObjectIn<Integer>, PacketObj
String command = data.getString(0x0001);
UUID target = (data.contains(0x0002)?data.getUUID(0x0002):null);
CommandSender sender = Bukkit.getConsoleSender();
if (target != null && (sender = Bukkit.getPlayer(target)) == null) {
client.sendPacket(new PacketExControlPlayer(6, tracker));
if (target != null) {
final Player player;
if ((player = Bukkit.getPlayer(target)) == null) {
client.sendPacket(new PacketExControlPlayer(6, tracker));
return;
} else {
AgnosticScheduler.following(player).runs(plugin, c -> Bukkit.getServer().dispatchCommand(player, command));
}
} else {
Bukkit.getServer().dispatchCommand(sender, command);
client.sendPacket(new PacketExControlPlayer(0, tracker));
AgnosticScheduler.global.runs(plugin, c -> Bukkit.getServer().dispatchCommand(Bukkit.getConsoleSender(), command));
}
client.sendPacket(new PacketExControlPlayer(0, tracker));
} catch (Throwable e) {
client.sendPacket(new PacketExControlPlayer(2, tracker));
e.printStackTrace();

View File

@ -3,6 +3,7 @@ package net.ME1312.SubServers.Client.Bukkit.Network.Packet;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.SubData.Client.Protocol.PacketObjectIn;
import net.ME1312.SubData.Client.SubDataSender;
import net.ME1312.SubServers.Client.Bukkit.Library.Compatibility.AgnosticScheduler;
import net.ME1312.SubServers.Client.Bukkit.SubPlugin;
import org.bukkit.Bukkit;
@ -26,7 +27,7 @@ public class PacketInExReload implements PacketObjectIn<Integer> {
public void receive(SubDataSender client, ObjectMap<Integer> data) {
if (data != null && data.contains(0x0000)) Bukkit.getLogger().warning("SubData > Received request for a plugin reload: " + data.getString(0x0000));
// else Bukkit.getLogger().warning("SubData > Received request for a plugin reload");
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
AgnosticScheduler.async.runs(plugin, c -> {
try {
plugin.reload(true);
} catch (Exception e) {

View File

@ -2,7 +2,6 @@ package net.ME1312.SubServers.Client.Bukkit.Network.Packet;
import net.ME1312.Galaxi.Library.Container.ContainedPair;
import net.ME1312.Galaxi.Library.Map.ObjectMap;
import net.ME1312.Galaxi.Library.Version.Version;
import net.ME1312.SubData.Client.Protocol.PacketObjectIn;
import net.ME1312.SubData.Client.SubDataSender;
import net.ME1312.SubServers.Client.Bukkit.Event.*;
@ -20,7 +19,7 @@ import java.util.function.Consumer;
* Run Event Packet
*/
public class PacketInExRunEvent implements PacketObjectIn<Integer> {
private static HashMap<String, List<Consumer<ObjectMap<String>>>> callbacks = new HashMap<String, List<Consumer<ObjectMap<String>>>>();
private static final HashMap<String, List<Consumer<ObjectMap<String>>>> callbacks = new HashMap<String, List<Consumer<ObjectMap<String>>>>();
/**
* New PacketInRunEvent
@ -58,7 +57,7 @@ public class PacketInExRunEvent implements PacketObjectIn<Integer> {
public void accept(ObjectMap<String> data) {
if (plugin.isEnabled()) {
Bukkit.getPluginManager().callEvent(new SubCreateEvent((data.contains("player"))?data.getUUID("player"):null, data.getString("host"), data.getString("name"),
data.getString("template"), (data.contains("version"))?new Version(data.getString("version")):null, data.getInt("port"), data.getBoolean("update")));
data.getString("template"), data.getVersion("version"), data.getInt("port"), data.getBoolean("update")));
callback("SubCreateEvent", this);
}
}
@ -68,7 +67,7 @@ public class PacketInExRunEvent implements PacketObjectIn<Integer> {
public void accept(ObjectMap<String> data) {
if (plugin.isEnabled()) {
Bukkit.getPluginManager().callEvent(new SubCreatedEvent((data.contains("player"))?data.getUUID("player"):null, data.getString("host"), data.getString("name"),
data.getString("template"), (data.contains("version"))?new Version(data.getString("version")):null, data.getInt("port"), data.getBoolean("update"), data.getBoolean("success")));
data.getString("template"), data.getVersion("version"), data.getInt("port"), data.getBoolean("update"), data.getBoolean("success")));
callback("SubCreatedEvent", this);
}
}
@ -159,17 +158,17 @@ public class PacketInExRunEvent implements PacketObjectIn<Integer> {
@SuppressWarnings("unchecked")
@Override
public void receive(SubDataSender client, ObjectMap<Integer> data) {
if (callbacks.keySet().contains(data.getString(0x0000))) {
List<Consumer<ObjectMap<String>>> callbacks = PacketInExRunEvent.callbacks.get(data.getString(0x0000));
PacketInExRunEvent.callbacks.remove(data.getString(0x0000));
for (Consumer<ObjectMap<String>> callback : callbacks) {
callback.accept(new ObjectMap<>((Map<String, ?>) data.getObject(0x0001)));
synchronized (callbacks) {
if (callbacks.containsKey(data.getString(0x0000))) {
for (Consumer<ObjectMap<String>> callback : PacketInExRunEvent.callbacks.remove(data.getString(0x0000))) {
callback.accept(new ObjectMap<>((Map<String, ?>) data.getObject(0x0001)));
}
}
}
}
public static void callback(String event, Consumer<ObjectMap<String>> callback) {
List<Consumer<ObjectMap<String>>> callbacks = (PacketInExRunEvent.callbacks.keySet().contains(event))? PacketInExRunEvent.callbacks.get(event):new ArrayList<Consumer<ObjectMap<String>>>();
List<Consumer<ObjectMap<String>>> callbacks = (PacketInExRunEvent.callbacks.containsKey(event))? PacketInExRunEvent.callbacks.get(event):new ArrayList<Consumer<ObjectMap<String>>>();
callbacks.add(callback);
PacketInExRunEvent.callbacks.put(event, callbacks);
}

Some files were not shown because too many files have changed in this diff Show More