Some changes to the TODOs

Removed the matcher thingy, I will just support regex
This commit is contained in:
Jaime Martinez Rincon 2017-06-28 23:24:24 +02:00
parent 5747b9f064
commit 0b9c5f5f6b
6 changed files with 238 additions and 17 deletions

View File

@ -3,14 +3,15 @@
[![Build Status](https://travis-ci.com/jaime29010/LobbyBalancer.svg?token=2yUi9WpA9QzSbJx9eTmy&branch=master)](https://travis-ci.com/jaime29010/LobbyBalancer) [![Build Status](https://travis-ci.com/jaime29010/LobbyBalancer.svg?token=2yUi9WpA9QzSbJx9eTmy&branch=master)](https://travis-ci.com/jaime29010/LobbyBalancer)
### Things to do: ### Things- to do:
- [x] Get dummy sections able to have already registered servers on other sections - [x] Get dummy sections able to have already registered servers on other sections
- [ ] Make `marker-descs` work per section - [x] Add a new message for when a player gets connected to a server and repurpose the connecting one
- [ ] Make the feature `marker-descs` work per section
- [ ] Unify the code that loads server into a section (duplicated at SectionManager and ServerSection) - [ ] Unify the code that loads server into a section (duplicated at SectionManager and ServerSection)
- [ ] Unify some of the code used in the FallbackCommand and SectionCommand - [ ] Unify some of the code used in the FallbackCommand and SectionCommand
- [ ] Make the way of matching a string configurable (wildcard, contains, similar, regex) - [ ] Use https://github.com/kennedyoliveira/pastebin4j instead of jpaste
- [ ] Make the section initialization work in stages instead of being hardcoded - [ ] (!) Make the section initialization work in stages instead of being hardcoded
- [ ] Ditch the faucet dependency and use [ConfigMe](https://github.com/AuthMe/ConfigMe) and [DependencyInjector](https://github.com/ljacqu/DependencyInjector) instead - [ ] (!) Ditch the faucet dependency and use [ConfigMe](https://github.com/AuthMe/ConfigMe) and [DependencyInjector](https://github.com/ljacqu/DependencyInjector) instead
- [ ] Use a separate file for configuring the sections, must be done alongside the forth item - [ ] Use a separate file for configuring the sections, must be done alongside the forth item
- [ ] Separate the types of connections in classes instead of being in ConnectionIntent - [ ] Separate the types of connections in classes instead of being in ConnectionIntent
- [ ] Make the plugin API be not so dependent on a instance of LobbyBalancer - [ ] Make the plugin API be not so dependent on a instance of LobbyBalancer

View File

@ -6,7 +6,7 @@
<groupId>me.jaimemartz</groupId> <groupId>me.jaimemartz</groupId>
<artifactId>lobbybalancer</artifactId> <artifactId>lobbybalancer</artifactId>
<version>2.0.9.8</version> <version>2.0.9.9</version>
<name>LobbyBalancer</name> <name>LobbyBalancer</name>
<properties> <properties>

View File

@ -42,6 +42,7 @@ public class ConfigEntries implements ConfigEntryHolder {
public static final ConfigEntry<Boolean> SERVERS_UPDATE = new ConfigEntry<>(0, "settings.servers-update", false); public static final ConfigEntry<Boolean> SERVERS_UPDATE = new ConfigEntry<>(0, "settings.servers-update", false);
public static final ConfigEntry<String> CONNECTING_MESSAGE = new ConfigEntry<>(0, "settings.messages.connecting-server", null); public static final ConfigEntry<String> CONNECTING_MESSAGE = new ConfigEntry<>(0, "settings.messages.connecting-server", null);
public static final ConfigEntry<String> CONNECTED_MESSAGE = new ConfigEntry<>(0, "settings.messages.connecting-server", null);
public static final ConfigEntry<String> FAILURE_MESSAGE = new ConfigEntry<>(0, "settings.messages.misc-failure", null); public static final ConfigEntry<String> FAILURE_MESSAGE = new ConfigEntry<>(0, "settings.messages.misc-failure", null);
public static final ConfigEntry<String> UNKNOWN_SECTION_MESSAGE = new ConfigEntry<>(0, "settings.messages.unknown-section", null); public static final ConfigEntry<String> UNKNOWN_SECTION_MESSAGE = new ConfigEntry<>(0, "settings.messages.unknown-section", null);
public static final ConfigEntry<String> INVALID_INPUT_MESSAGE = new ConfigEntry<>(0, "settings.messages.invalid-input", null); public static final ConfigEntry<String> INVALID_INPUT_MESSAGE = new ConfigEntry<>(0, "settings.messages.invalid-input", null);

View File

@ -24,6 +24,10 @@ public abstract class ConnectionIntent {
this.player = player; this.player = player;
this.section = section; this.section = section;
new Messager(player).send(ConfigEntries.CONNECTING_MESSAGE.get(),
new Replacement("{section}", section.getName())
);
if (servers == section.getServers()) { if (servers == section.getServers()) {
throw new IllegalStateException("The servers list parameter is the same object as the section servers list, this cannot happen"); throw new IllegalStateException("The servers list parameter is the same object as the section servers list, this cannot happen");
} }
@ -31,10 +35,10 @@ public abstract class ConnectionIntent {
if (section.getProvider() != ProviderType.NONE) { if (section.getProvider() != ProviderType.NONE) {
ServerInfo target = this.fetchServer(plugin, player, section, provider, servers); ServerInfo target = this.fetchServer(plugin, player, section, provider, servers);
if (target != null) { if (target != null) {
new Messager(player).send(ConfigEntries.CONNECTING_MESSAGE.get(), this.connect(target);
new Messager(player).send(ConfigEntries.CONNECTED_MESSAGE.get(),
new Replacement("{server}", target.getName()) new Replacement("{server}", target.getName())
); );
this.connect(target);
} else { } else {
new Messager(player).send(ConfigEntries.FAILURE_MESSAGE.get()); new Messager(player).send(ConfigEntries.FAILURE_MESSAGE.get());
} }

View File

@ -0,0 +1,200 @@
package me.jaimemartz.lobbybalancer.utils;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.chat.ComponentSerializer;
import net.md_5.bungee.chat.TextComponentSerializer;
import net.md_5.bungee.chat.TranslatableComponentSerializer;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.List;
public class ServerListPing {
private int timeout = 7000;
private static Gson gson = new GsonBuilder()
.registerTypeAdapter(BaseComponent.class, new ComponentSerializer())
.registerTypeAdapter(TextComponent.class, new TextComponentSerializer())
.registerTypeAdapter(TranslatableComponentSerializer.class, new TranslatableComponentSerializer())
.create();
private static int readVarInt(DataInputStream in) throws IOException {
int i = 0;
int j = 0;
while (true) {
int k = in.readByte();
i |= (k & 0x7F) << j++ * 7;
if (j > 5) throw new RuntimeException("VarInt too big");
if ((k & 0x80) != 128) break;
}
return i;
}
private static void writeVarInt(DataOutputStream out, int paramInt) throws IOException {
while (true) {
if ((paramInt & 0xFFFFFF80) == 0) {
out.writeByte(paramInt);
return;
}
out.writeByte(paramInt & 0x7F | 0x80);
paramInt >>>= 7;
}
}
public StatusResponse ping(InetSocketAddress host) throws IOException {
try (Socket socket = new Socket()) {
socket.setSoTimeout(timeout);
socket.connect(host, timeout);
try (DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
DataInputStream dataInputStream = new DataInputStream(socket.getInputStream())) {
ByteArrayOutputStream b = new ByteArrayOutputStream();
DataOutputStream handshake = new DataOutputStream(b);
handshake.writeByte(0x00); //packet id for handshake
writeVarInt(handshake, 4); //protocol version
writeVarInt(handshake, host.getHostString().length()); //host length
handshake.writeBytes(host.getHostString()); //host string
handshake.writeShort(host.getPort()); //port
writeVarInt(handshake, 1); //state (1 for handshake)
writeVarInt(dataOutputStream, b.size()); //prepend size
dataOutputStream.write(b.toByteArray()); //write handshake packet
dataOutputStream.writeByte(0x01); //size is only 1
dataOutputStream.writeByte(0x00); //packet id for ping
int size = readVarInt(dataInputStream); //size of packet
int id = readVarInt(dataInputStream); //packet id
if (id == -1) {
throw new IOException("Premature end of stream.");
}
if (id != 0x00) { //we want a status response
throw new IOException("Invalid packetID");
}
int length = readVarInt(dataInputStream); //length of json string
if (length == -1) {
throw new IOException("Premature end of stream.");
}
if (length == 0) {
throw new IOException("Invalid string length.");
}
byte[] in = new byte[length];
dataInputStream.readFully(in); //read json string
String json = new String(in);
long now = System.currentTimeMillis();
dataOutputStream.writeByte(0x09); //size of packet
dataOutputStream.writeByte(0x01); //0x01 for ping
dataOutputStream.writeLong(now); //time!?
readVarInt(dataInputStream);
id = readVarInt(dataInputStream);
if (id == -1) {
throw new IOException("Premature end of stream.");
}
if (id != 0x01) {
throw new IOException("Invalid packetID");
}
long pingtime = dataInputStream.readLong(); //read response
StatusResponse response = gson.fromJson(json, StatusResponse.class);
response.time = (int) (now - pingtime);
return response;
}
}
}
public void setTimeout(int timeout) {
this.timeout = timeout;
}
public int getTimeout() {
return timeout;
}
public static class StatusResponse {
private BaseComponent description;
private Players players;
private Version version;
private String favicon;
private int time;
public BaseComponent getDescription() {
return description;
}
public Players getPlayers() {
return players;
}
public Version getVersion() {
return version;
}
public String getFavicon() {
return favicon;
}
public int getTime() {
return time;
}
public static class Players {
private int max;
private int online;
private List<Player> sample;
public int getMax() {
return max;
}
public int getOnline() {
return online;
}
public List<Player> getSample() {
return sample;
}
}
public static class Player {
private String name;
private String id;
public String getName() {
return name;
}
public String getId() {
return id;
}
}
public static class Version {
private String name;
private String protocol;
public String getName() {
return name;
}
public String getProtocol() {
return protocol;
}
}
}
}

View File

@ -91,6 +91,23 @@ settings:
rules: rules:
'section-from': 'section-to' 'section-from': 'section-to'
# This will determine how the plugin if a string matches other string
string-matcher:
# Matches when the string is like the other string
# ? for one character, * for any number of characters
wildcard: true
# Matches when the string contains the other string
contains: false
# Matches when the string matches the pattern of the other string
regex: false
# Matches when both strings are very similar
# See https://en.wikipedia.org/wiki/Levenshtein_distance
# Set to 100 to disable it, or other value to match when the result is higher than it
similar: 100
# This will reload the plugin every time you execute /greload # This will reload the plugin every time you execute /greload
auto-reload: true auto-reload: true
@ -110,7 +127,8 @@ settings:
# Comment a message to disable it # Comment a message to disable it
messages: messages:
connecting-server: '&aConnecting to {server}' # connecting-server: '&aConnecting to a {section} server'
connected-server: '&aConnected to {server}'
misc-failure: '&cCould not find a server to get connected' misc-failure: '&cCould not find a server to get connected'
unknown-section: '&cCould not find a section with that name' unknown-section: '&cCould not find a section with that name'
invalid-input: '&cThis is an invalid input type for this command' invalid-input: '&cThis is an invalid input type for this command'
@ -137,18 +155,15 @@ sections:
auth-lobbies: auth-lobbies:
provider: RANDOM provider: RANDOM
servers: ["Auth1", "Auth2", "Auth3"] servers: ["Auth1", "Auth2", "Auth3"]
general-lobbies: general-lobbies:
parent: 'auth-lobbies' parent: 'auth-lobbies'
principal: true principal: true # Cannot get above the principal section
provider: RANDOM provider: RANDOM
servers: ["Lobby1", "Lobby2", "Lobby3"] servers: ["Lobby1", "Lobby2", "Lobby3"]
skywars-lobbies: skywars-lobbies:
parent: 'general-lobbies' parent: 'general-lobbies'
parent: LOWEST parent: LOWEST
servers: ["SWLobby1", "SWLobby2", "SWLobby3"] servers: ["SWLobby1", "SWLobby2", "SWLobby3"]
skywars-games: skywars-games:
provider: FILLER provider: FILLER
parent: 'skywars-lobbies' parent: 'skywars-lobbies'
@ -156,13 +171,13 @@ sections:
"SW_A1", "SW_A2", "SW_A3", "SW_A4", "SW_A5", "SW_A1", "SW_A2", "SW_A3", "SW_A4", "SW_A5",
"SW_B1", "SW_B2", "SW_B3", "SW_B4", "SW_B5" "SW_B1", "SW_B2", "SW_B3", "SW_B4", "SW_B5"
] ]
section-server: 'randomskywars' section-server: 'randomskywars' # Creates a fake server you can use, ex: @randomskywars
section-command: section-command:
name: 'playskywars' name: 'playskywars'
permission: '' permission: ''
aliases: ["skywars"] aliases: ["skywars"]
skywars-typea: skywars-typea:
dummy: true dummy: true # Use servers already registered on skywars-games
parent: 'skywars-lobbies' parent: 'skywars-lobbies'
servers: ["SW_A1", "SW_A2", "SW_A3", "SW_A4", "SW_A5"] servers: ["SW_A1", "SW_A2", "SW_A3", "SW_A4", "SW_A5"]
section-server: 'skywarstypea' section-server: 'skywarstypea'