SubServers-2/SubServers.Client/Bukkit/src/net/ME1312/SubServers/Client/Bukkit/Network/SubDataClient.java

242 lines
9.2 KiB
Java

package net.ME1312.SubServers.Client.Bukkit.Network;
import net.ME1312.SubServers.Client.Bukkit.Library.Exception.IllegalPacketException;
import net.ME1312.SubServers.Client.Bukkit.Library.Version.Version;
import net.ME1312.SubServers.Client.Bukkit.Network.Packet.*;
import net.ME1312.SubServers.Client.Bukkit.SubPlugin;
import org.bukkit.Bukkit;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.net.InetAddress;
import java.net.Socket;
import java.util.HashMap;
public final class SubDataClient {
private static HashMap<Class<? extends PacketOut>, String> pOut = new HashMap<Class<? extends PacketOut>, String>();
private static HashMap<String, PacketIn> pIn = new HashMap<String, PacketIn>();
private static boolean defaults = false;
private PrintWriter writer;
private Socket socket;
private String name;
private SubPlugin plugin;
/**
* SubServers Client Instance
*
* @param plugin SubPlugin
* @param address Bind Address
* @param port Port
* @throws IOException
*/
public SubDataClient(SubPlugin plugin, String name, InetAddress address, int port) throws IOException {
socket = new Socket(address, port);
this.plugin = plugin;
this.name = name;
this.writer = new PrintWriter(socket.getOutputStream(), true);
if (!defaults) loadDefaults();
loop();
Bukkit.getScheduler().runTaskLater(plugin, () -> sendPacket(new PacketAuthorization(plugin)), 10);
}
private void loadDefaults() {
defaults = true;
registerPacket(new PacketAuthorization(plugin), "Authorization");
registerPacket(new PacketCommandServer(), "SubCommandServer");
registerPacket(new PacketCreateServer(), "SubCreateServer");
registerPacket(new PacketDownloadHostInfo(), "SubDownloadHostInfo");
registerPacket(new PacketDownloadLang(plugin), "SubDownloadLang");
registerPacket(new PacketDownloadPlayerList(), "SubDownloadPlayerList");
registerPacket(new PacketDownloadServerInfo(), "SubDownloadServerInfo");
registerPacket(new PacketDownloadServerList(), "SubDownloadServerList");
registerPacket(new PacketInfoPassthrough(), "SubInfoPassthrough");
registerPacket(new PacketInRunEvent(), "SubRunEvent");
registerPacket(new PacketInShutdown(), "SubShutdown");
registerPacket(new PacketLinkServer(plugin), "SubLinkServer");
registerPacket(new PacketStartServer(), "SubStartServer");
registerPacket(new PacketStopServer(), "SubStopServer");
registerPacket(new PacketTeleportPlayer(), "SubTeleportPlayer");
registerPacket(PacketAuthorization.class, "Authorization");
registerPacket(PacketCommandServer.class, "SubCommandServer");
registerPacket(PacketCreateServer.class, "SubCreateServer");
registerPacket(PacketDownloadHostInfo.class, "SubDownloadHostInfo");
registerPacket(PacketDownloadLang.class, "SubDownloadLang");
registerPacket(PacketDownloadPlayerList.class, "SubDownloadPlayerList");
registerPacket(PacketDownloadServerInfo.class, "SubDownloadServerInfo");
registerPacket(PacketDownloadServerList.class, "SubDownloadServerList");
registerPacket(PacketInfoPassthrough.class, "SubInfoPassthrough");
registerPacket(PacketLinkServer.class, "SubLinkServer");
registerPacket(PacketStartServer.class, "SubStartServer");
registerPacket(PacketStopServer.class, "SubStopServer");
registerPacket(PacketTeleportPlayer.class, "SubTeleportPlayer");
}
private void loop() {
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
try {
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String input;
while ((input = in.readLine()) != null) {
try {
JSONObject json = new JSONObject(input);
PacketIn packet = decodePacket(json);
try {
packet.execute((json.keySet().contains("c")) ? json.getJSONObject("c") : null);
} catch (Exception e) {
new InvocationTargetException(e, "Exception while executing PacketIn").printStackTrace();
}
} catch (IllegalPacketException e) {
e.printStackTrace();
} catch (JSONException e) {
new IllegalPacketException("Unknown Packet Format: " + input).printStackTrace();
}
}
try {
destroy(true);
} catch (IOException e1) {
e1.printStackTrace();
}
} catch (Exception e) {
if (e.getMessage() == null || !e.getMessage().equals("Socket closed")) e.printStackTrace();
try {
destroy(true);
} catch (IOException e1) {
e1.printStackTrace();
}
}
});
}
/**
* Gets the Assigned Server Name
*
* @return Server Name
*/
public String getName() {
return name;
}
/**
* Gets the Server Socket
*
* @return Server Socket
*/
public Socket getClient() {
return socket;
}
/**
* Register Packet to the Network
*
* @param packet PacketIn to register
* @param handle Handle to Bind
*/
public static void registerPacket(PacketIn packet, String handle) {
pIn.put(handle, packet);
}
/**
* Register Packet to the Network
*
* @param packet PacketOut to register
* @param handle Handle to bind
*/
public static void registerPacket(Class<? extends PacketOut> packet, String handle) {
pOut.put(packet, handle);
}
/**
* Grab PacketIn Instance via handle
*
* @param handle Handle
* @return PacketIn
*/
public static PacketIn getPacket(String handle) {
return pIn.get(handle);
}
/**
* Send Packet to Client
*
* @param packet Packet to send
*/
public void sendPacket(PacketOut packet) {
try {
writer.println(encodePacket(packet));
} catch (IllegalPacketException e) {
e.printStackTrace();
}
}
/**
* JSON Encode PacketOut
*
* @param packet PacketOut
* @return JSON Formatted Packet
* @throws IllegalPacketException
*/
protected static JSONObject encodePacket(PacketOut packet) throws IllegalPacketException {
JSONObject json = new JSONObject();
if (!pOut.keySet().contains(packet.getClass())) throw new IllegalPacketException("Unknown PacketOut Channel: " + packet.getClass().getCanonicalName());
if (packet.getVersion().toString() == null) throw new NullPointerException("PacketOut Version cannot be null: " + packet.getClass().getCanonicalName());
JSONObject contents = packet.generate();
json.put("h", pOut.get(packet.getClass()));
json.put("v", packet.getVersion().toString());
if (contents != null) json.put("c", contents);
return json;
}
/**
* JSON Decode PacketIn
*
* @param json JSON to Decode
* @return PacketIn
* @throws IllegalPacketException
* @throws InvocationTargetException
*/
protected static PacketIn decodePacket(JSONObject json) throws IllegalPacketException, InvocationTargetException {
if (!json.keySet().contains("h") || !json.keySet().contains("v")) throw new IllegalPacketException("Unknown Packet Format: " + json.toString());
if (!pIn.keySet().contains(json.getString("h"))) throw new IllegalPacketException("Unknown PacketIn Channel: " + json.getString("h"));
PacketIn packet = pIn.get(json.getString("h"));
if (!new Version(json.getString("v")).equals(packet.getVersion())) throw new IllegalPacketException("Packet Version Mismatch in " + json.getString("h") + ": " + json.getString("v") + "->" + packet.getVersion().toString());
return packet;
}
/**
* Drops All Connections and Stops the SubData Listener
*
* @throws IOException
*/
public void destroy(boolean reconnect) throws IOException {
if (socket != null) {
final Socket socket = this.socket;
this.socket = null;
if (!socket.isClosed()) socket.close();
Bukkit.getLogger().info("SubServers > The SubData Connection was closed");
if (reconnect) {
Bukkit.getLogger().info("SubServers > Attempting to reconnect in 10 seconds");
Bukkit.getScheduler().runTaskLater(plugin, () -> {
try {
plugin.subdata = new SubDataClient(plugin, name, socket.getInetAddress(), socket.getPort());
} catch (IOException e) {
e.printStackTrace();
}
}, 10 * 20);
}
plugin.subdata = null;
}
}
}