Framework adjustment
This commit is contained in:
134
src/main/scala/io/izzel/taboolib/client/TabooLibClient.java
Normal file
134
src/main/scala/io/izzel/taboolib/client/TabooLibClient.java
Normal file
@@ -0,0 +1,134 @@
|
||||
package io.izzel.taboolib.client;
|
||||
|
||||
import io.izzel.taboolib.TabooLib;
|
||||
import io.izzel.taboolib.client.packet.Packet;
|
||||
import io.izzel.taboolib.client.packet.impl.PacketCommand;
|
||||
import io.izzel.taboolib.client.packet.impl.PacketMessage;
|
||||
import io.izzel.taboolib.module.locale.TLocale;
|
||||
import io.izzel.taboolib.module.command.lite.CommandBuilder;
|
||||
import io.izzel.taboolib.client.packet.PacketSerializer;
|
||||
import io.izzel.taboolib.util.ArrayUtil;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.util.NumberConversions;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-08-22 22:27
|
||||
*/
|
||||
public class TabooLibClient {
|
||||
|
||||
private static Socket socket;
|
||||
private static BufferedReader reader;
|
||||
private static PrintWriter writer;
|
||||
private static ExecutorService executorService = Executors.newCachedThreadPool();
|
||||
private static Packet packet;
|
||||
private static boolean notify = false;
|
||||
private static long latestResponse = System.currentTimeMillis();
|
||||
|
||||
public static void init() {
|
||||
if (TabooLibSettings.load()) {
|
||||
connect();
|
||||
Bukkit.getScheduler().runTaskTimerAsynchronously(TabooLib.getPlugin(), TabooLibClient::reconnect, 0, 100);
|
||||
} else {
|
||||
TLocale.sendToConsole("COMMUNICATION.FAILED-LOAD-SETTINGS", TabooLibSettings.getThrowable().toString());
|
||||
}
|
||||
}
|
||||
|
||||
public static void sendPacket(Packet packet) {
|
||||
writer.println(PacketSerializer.serialize(packet));
|
||||
}
|
||||
|
||||
public static void reconnect() {
|
||||
if (System.currentTimeMillis() - latestResponse > NumberConversions.toInt(TabooLibSettings.getSettings().getProperty("channel.timeout"))) {
|
||||
connect();
|
||||
}
|
||||
}
|
||||
|
||||
public static void connect() {
|
||||
try {
|
||||
if (socket != null) {
|
||||
socket.close();
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
|
||||
try {
|
||||
socket = new Socket("localhost", NumberConversions.toInt(TabooLibSettings.getSettings().getProperty("channel.port")));
|
||||
reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), TabooLibSettings.getCharset()));
|
||||
writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(), TabooLibSettings.getCharset()), true);
|
||||
notify = false;
|
||||
TLocale.sendToConsole("COMMUNICATION.SUCCESS-CONNECTED");
|
||||
} catch (SocketException e) {
|
||||
return;
|
||||
} catch (IOException e) {
|
||||
TLocale.sendToConsole("COMMUNICATION.FAILED-CONNECT-CLIENT", e.getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
executorService.execute(() -> {
|
||||
try {
|
||||
while (!socket.isClosed() && (packet = PacketSerializer.unSerialize(reader.readLine())) != null) {
|
||||
packet.readOnClient();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
TLocale.sendToConsole("COMMUNICATION.FAILED-READING-PACKET", e.getMessage());
|
||||
}
|
||||
});
|
||||
|
||||
CommandBuilder.create("TabooLibClient", TabooLib.getPlugin())
|
||||
.aliases("tclient")
|
||||
.permission("*")
|
||||
.execute((sender, args) -> {
|
||||
if (args.length == 0) {
|
||||
sender.sendMessage("§c[TabooLibClient] §f/tclient message §7[TEXT] §8- §7发送测试信息");
|
||||
sender.sendMessage("§c[TabooLibClient] §f/tclient command §7[TEXT] §8- §7发送测试命令");
|
||||
} else if (args[0].equalsIgnoreCase("message") && args.length > 1) {
|
||||
sendPacket(new PacketMessage(ArrayUtil.arrayJoin(args, 1)));
|
||||
} else if (args[0].equalsIgnoreCase("command") && args.length > 1) {
|
||||
sendPacket(new PacketCommand(ArrayUtil.arrayJoin(args, 1)));
|
||||
} else {
|
||||
sender.sendMessage("§c[TabooLibClient] §7指令错误.");
|
||||
}
|
||||
}).build();
|
||||
}
|
||||
|
||||
// *********************************
|
||||
//
|
||||
// Getter and Setter
|
||||
//
|
||||
// *********************************
|
||||
|
||||
public static Socket getSocket() {
|
||||
return socket;
|
||||
}
|
||||
|
||||
public static BufferedReader getReader() {
|
||||
return reader;
|
||||
}
|
||||
|
||||
public static PrintWriter getWriter() {
|
||||
return writer;
|
||||
}
|
||||
|
||||
public static ExecutorService getExecutorService() {
|
||||
return executorService;
|
||||
}
|
||||
|
||||
public static Packet getLatestPacket() {
|
||||
return packet;
|
||||
}
|
||||
|
||||
public static long getLatestResponse() {
|
||||
return latestResponse;
|
||||
}
|
||||
|
||||
public static void setLatestResponse(long latestResponse) {
|
||||
TabooLibClient.latestResponse = latestResponse;
|
||||
}
|
||||
}
|
||||
122
src/main/scala/io/izzel/taboolib/client/TabooLibServer.java
Normal file
122
src/main/scala/io/izzel/taboolib/client/TabooLibServer.java
Normal file
@@ -0,0 +1,122 @@
|
||||
package io.izzel.taboolib.client;
|
||||
|
||||
import io.izzel.taboolib.TabooLibAPI;
|
||||
import io.izzel.taboolib.client.packet.Packet;
|
||||
import io.izzel.taboolib.client.packet.PacketSerializer;
|
||||
import io.izzel.taboolib.client.packet.impl.PacketHeartbeat;
|
||||
import io.izzel.taboolib.client.server.ClientConnection;
|
||||
import io.izzel.taboolib.client.packet.impl.PacketQuit;
|
||||
import org.bukkit.util.NumberConversions;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 研究了一个小时 log4j 愣是没整明白,不搞那些高端日志工具了
|
||||
*
|
||||
* @Author sky
|
||||
* @Since 2018-08-22 20:45
|
||||
*/
|
||||
public class TabooLibServer {
|
||||
|
||||
private static SimpleDateFormat infoFormat = new SimpleDateFormat("HH:mm:ss");
|
||||
private static ServerSocket server = null;
|
||||
private static ExecutorService executorService = Executors.newCachedThreadPool();
|
||||
private static ConcurrentHashMap<Integer, ClientConnection> client = new ConcurrentHashMap<>();
|
||||
|
||||
public static void main(String[] args) {
|
||||
println("TabooLib Communication Area Starting...");
|
||||
|
||||
if (!TabooLibSettings.load()) {
|
||||
println("Settings loading failed: " + TabooLibSettings.getThrowable().toString());
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
server = new ServerSocket(NumberConversions.toInt(TabooLibSettings.getSettings().getProperty("channel.port")));
|
||||
println("Starting TabooLib server on " + server.getInetAddress().getHostName() + ":" + server.getLocalPort());
|
||||
} catch (IOException e) {
|
||||
println("Server starting failed: " + e.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(() -> {
|
||||
/*
|
||||
向所有已连接的客户端发送心跳包
|
||||
*/
|
||||
sendPacket(new PacketHeartbeat(0));
|
||||
/*
|
||||
检测无效的客户端连接,如果超过 5000 毫秒没有收到客户端的回应(上一次心跳包的回应)则注销链接
|
||||
*/
|
||||
client.entrySet().stream().filter(connection -> !connection.getValue().isAlive()).map(connection -> new PacketQuit(connection.getKey(), "Lost connection")).forEach(TabooLibServer::sendPacket);
|
||||
}, 0, 1, TimeUnit.SECONDS);
|
||||
|
||||
/*
|
||||
异步接收连接请求
|
||||
*/
|
||||
Executors.newSingleThreadScheduledExecutor().execute(() -> {
|
||||
while (true) {
|
||||
try {
|
||||
Socket socket = server.accept();
|
||||
ClientConnection connection = new ClientConnection(socket);
|
||||
client.put(socket.getPort(), connection);
|
||||
executorService.execute(connection);
|
||||
println("Client accepted: " + socket.getPort() + " online: " + client.size());
|
||||
} catch (Exception e) {
|
||||
println("Client accept failed: " + e.toString());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void sendPacket(Packet packet) {
|
||||
sendPacket(PacketSerializer.serialize(packet));
|
||||
}
|
||||
|
||||
public static void sendPacket(String origin) {
|
||||
// 在服务端尝试解析动作并运行
|
||||
Optional.ofNullable(PacketSerializer.unSerialize(origin)).ifPresent(Packet::readOnServer);
|
||||
// 将动作发送至所有客户端
|
||||
for (ClientConnection connection : TabooLibServer.getClient().values()) {
|
||||
try {
|
||||
connection.getWriter().println(origin);
|
||||
} catch (Exception e) {
|
||||
TabooLibServer.println("Packet sending failed: " + e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void println(Object obj) {
|
||||
System.out.println(TabooLibAPI.isBukkit() ? obj : "[" + infoFormat.format(System.currentTimeMillis()) + " INFO]: " + obj);
|
||||
}
|
||||
|
||||
public static Optional<Map.Entry<Integer, ClientConnection>> getConnection(int port) {
|
||||
return client.entrySet().stream().filter(entry -> entry.getKey().equals(port)).findFirst();
|
||||
}
|
||||
|
||||
// *********************************
|
||||
//
|
||||
// Getter and Setter
|
||||
//
|
||||
// *********************************
|
||||
|
||||
public static ServerSocket getServer() {
|
||||
return server;
|
||||
}
|
||||
|
||||
public static ConcurrentHashMap<Integer, ClientConnection> getClient() {
|
||||
return client;
|
||||
}
|
||||
|
||||
public static ExecutorService getExecutorService() {
|
||||
return executorService;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package io.izzel.taboolib.client;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-08-22 23:55
|
||||
*/
|
||||
public class TabooLibSettings {
|
||||
|
||||
private static Charset charset = Charset.forName("UTF-8");
|
||||
private static Properties settings = new Properties();
|
||||
private static Throwable throwable;
|
||||
|
||||
public static boolean load() {
|
||||
try {
|
||||
settings.load(getSettingsInputStream());
|
||||
return true;
|
||||
} catch (Throwable e) {
|
||||
throwable = e;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static InputStream getSettingsInputStream() {
|
||||
try {
|
||||
URL url = TabooLibServer.class.getClassLoader().getResource("settings.properties");
|
||||
if (url == null) {
|
||||
return null;
|
||||
} else {
|
||||
URLConnection connection = url.openConnection();
|
||||
connection.setUseCaches(false);
|
||||
return connection.getInputStream();
|
||||
}
|
||||
} catch (IOException ignored) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// *********************************
|
||||
//
|
||||
// Getter and Setter
|
||||
//
|
||||
// *********************************
|
||||
|
||||
public static Properties getSettings() {
|
||||
return settings;
|
||||
}
|
||||
|
||||
public static Throwable getThrowable() {
|
||||
return throwable;
|
||||
}
|
||||
|
||||
public static Charset getCharset() {
|
||||
return charset;
|
||||
}
|
||||
}
|
||||
45
src/main/scala/io/izzel/taboolib/client/packet/Packet.java
Normal file
45
src/main/scala/io/izzel/taboolib/client/packet/Packet.java
Normal file
@@ -0,0 +1,45 @@
|
||||
package io.izzel.taboolib.client.packet;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-08-22 23:01
|
||||
*/
|
||||
public abstract class Packet {
|
||||
|
||||
private final int port;
|
||||
private final String uid;
|
||||
|
||||
public Packet(int port) {
|
||||
this.port = port;
|
||||
this.uid = UUID.randomUUID().toString();
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public String getUid() {
|
||||
return uid;
|
||||
}
|
||||
|
||||
public void readOnServer() {
|
||||
|
||||
}
|
||||
|
||||
public void readOnClient() {
|
||||
|
||||
}
|
||||
|
||||
public void serialize(JsonObject json) {
|
||||
|
||||
}
|
||||
|
||||
public void unSerialize(JsonObject json) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package io.izzel.taboolib.client.packet;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import io.izzel.taboolib.TabooLib;
|
||||
import io.izzel.taboolib.util.Files;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-08-22 23:07
|
||||
*/
|
||||
public class PacketParser {
|
||||
|
||||
private List<Class<?>> packets = new ArrayList<>();
|
||||
|
||||
public PacketParser() {
|
||||
Files.getClasses(TabooLib.getPlugin()).stream().filter(clazz -> clazz.isAnnotationPresent(PacketType.class)).forEach(clazz -> packets.add(clazz));
|
||||
}
|
||||
|
||||
public Packet parser(JsonObject json) {
|
||||
if (!json.has("packet")) {
|
||||
return null;
|
||||
}
|
||||
String packetType = json.get("packet").getAsString();
|
||||
Optional<Class<?>> packetFind = packets.stream().filter(packet -> packet.getAnnotation(PacketType.class).name().equals(packetType)).findFirst();
|
||||
if (!packetFind.isPresent()) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
Packet packetObject = (Packet) packetFind.get().getConstructor(Integer.TYPE).newInstance(json.get("port").getAsInt());
|
||||
packetObject.unSerialize(json);
|
||||
Arrays.stream(packetObject.getClass().getDeclaredFields()).filter(field -> field.isAnnotationPresent(PacketValue.class)).forEach(field -> {
|
||||
field.setAccessible(true);
|
||||
try {
|
||||
switch (field.getType().getSimpleName().toLowerCase()) {
|
||||
case "double":
|
||||
field.set(packetObject, json.get(field.getName()).getAsDouble());
|
||||
break;
|
||||
case "long":
|
||||
field.set(packetObject, json.get(field.getName()).getAsLong());
|
||||
break;
|
||||
case "short":
|
||||
field.set(packetObject, json.get(field.getName()).getAsShort());
|
||||
break;
|
||||
case "boolean":
|
||||
field.set(packetObject, json.get(field.getName()).getAsBoolean());
|
||||
break;
|
||||
case "string":
|
||||
field.set(packetObject, json.get(field.getName()).getAsString());
|
||||
break;
|
||||
case "number":
|
||||
field.set(packetObject, json.get(field.getName()).getAsNumber());
|
||||
break;
|
||||
case "int":
|
||||
case "integer":
|
||||
field.set(packetObject, json.get(field.getName()).getAsInt());
|
||||
break;
|
||||
case "char":
|
||||
case "character":
|
||||
field.set(packetObject, json.get(field.getName()).getAsCharacter());
|
||||
break;
|
||||
default:
|
||||
System.out.println("UnSerialize: Invalid packet value: " + field.getName());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
return packetObject;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// *********************************
|
||||
//
|
||||
// Getter and Setter
|
||||
//
|
||||
// *********************************
|
||||
|
||||
public List<Class<?>> getPackets() {
|
||||
return packets;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
package io.izzel.taboolib.client.packet;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import io.izzel.taboolib.TabooLibAPI;
|
||||
import io.izzel.taboolib.TabooLibLoader;
|
||||
import io.izzel.taboolib.client.packet.impl.PacketEmpty;
|
||||
import io.izzel.taboolib.module.inject.TListener;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.server.PluginDisableEvent;
|
||||
import org.bukkit.event.server.PluginEnableEvent;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-08-22 23:32
|
||||
*/
|
||||
@TListener
|
||||
public class PacketSerializer implements Listener {
|
||||
|
||||
private static PacketParser parser = new PacketParser();
|
||||
|
||||
public PacketSerializer() {
|
||||
loadPacket();
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onEnable(PluginEnableEvent e) {
|
||||
loadPacket(e.getPlugin());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onDisable(PluginDisableEvent e) {
|
||||
unloadPacket(e.getPlugin());
|
||||
}
|
||||
|
||||
public static void loadPacket() {
|
||||
Arrays.stream(Bukkit.getPluginManager().getPlugins()).forEach(PacketSerializer::loadPacket);
|
||||
}
|
||||
|
||||
public static void loadPacket(Plugin plugin) {
|
||||
if (plugin.getName().equals("TabooLib") || TabooLibAPI.isDependTabooLib(plugin)) {
|
||||
TabooLibLoader.getPluginClasses(plugin).ifPresent(classes -> classes.stream().filter(pluginClass -> pluginClass.isAnnotationPresent(PacketType.class)).forEach(pluginClass -> parser.getPackets().add(pluginClass)));
|
||||
}
|
||||
}
|
||||
|
||||
public static void unloadPacket() {
|
||||
Arrays.stream(Bukkit.getPluginManager().getPlugins()).forEach(PacketSerializer::unloadPacket);
|
||||
}
|
||||
|
||||
public static void unloadPacket(Plugin plugin) {
|
||||
if (plugin.getName().equals("TabooLib") || TabooLibAPI.isDependTabooLib(plugin)) {
|
||||
TabooLibLoader.getPluginClasses(plugin).ifPresent(classes -> classes.stream().filter(pluginClass -> pluginClass.isAnnotationPresent(PacketType.class)).forEach(pluginClass -> parser.getPackets().remove(pluginClass)));
|
||||
}
|
||||
}
|
||||
|
||||
public static String serialize(Packet packet) {
|
||||
JsonObject json = new JsonObject();
|
||||
packet.serialize(json);
|
||||
json.addProperty("uid", packet.getUid());
|
||||
json.addProperty("port", packet.getPort());
|
||||
json.addProperty("packet", packet.getClass().getAnnotation(PacketType.class).name());
|
||||
Arrays.stream(packet.getClass().getDeclaredFields()).filter(field -> field.isAnnotationPresent(PacketValue.class)).forEach(field -> {
|
||||
field.setAccessible(true);
|
||||
try {
|
||||
Object obj = field.get(packet);
|
||||
if (obj instanceof Number) {
|
||||
json.addProperty(field.getName(), (Number) obj);
|
||||
} else if (obj instanceof Boolean) {
|
||||
json.addProperty(field.getName(), (Boolean) obj);
|
||||
} else if (obj instanceof String) {
|
||||
json.addProperty(field.getName(), (String) obj);
|
||||
} else if (obj instanceof Character) {
|
||||
json.addProperty(field.getName(), (Character) obj);
|
||||
} else {
|
||||
System.out.println("Serialize: Invalid packet value: " + field.getName());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
return json.toString();
|
||||
}
|
||||
|
||||
public static Packet unSerialize(String origin) {
|
||||
Packet packet = null;
|
||||
try {
|
||||
packet = parser.parser((JsonObject) new JsonParser().parse(origin));
|
||||
} catch (JsonSyntaxException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return packet == null ? new PacketEmpty(0) : packet;
|
||||
}
|
||||
|
||||
// *********************************
|
||||
//
|
||||
// Getter and Setter
|
||||
//
|
||||
// *********************************
|
||||
|
||||
public static PacketParser getParser() {
|
||||
return parser;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package io.izzel.taboolib.client.packet;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-08-22 23:09
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface PacketType {
|
||||
|
||||
String name();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package io.izzel.taboolib.client.packet;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 使用该注解的成员变量
|
||||
* 将会被自动序列化
|
||||
*
|
||||
* 仅限以下类型:
|
||||
* - Number
|
||||
* - String
|
||||
* - Boolean
|
||||
* - Character
|
||||
*
|
||||
* @Author sky
|
||||
* @Since 2018-08-22 23:09
|
||||
*/
|
||||
@Target(ElementType.FIELD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface PacketValue {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package io.izzel.taboolib.client.packet.impl;
|
||||
|
||||
import io.izzel.taboolib.client.TabooLibServer;
|
||||
import io.izzel.taboolib.client.packet.Packet;
|
||||
import io.izzel.taboolib.client.packet.PacketType;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-08-22 23:01
|
||||
*/
|
||||
@PacketType(name = "alive")
|
||||
public class PacketAlive extends Packet {
|
||||
|
||||
public PacketAlive(int port) {
|
||||
super(port);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readOnServer() {
|
||||
TabooLibServer.getConnection(getPort()).ifPresent(connect -> connect.getValue().setLatestResponse(System.currentTimeMillis()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readOnClient() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package io.izzel.taboolib.client.packet.impl;
|
||||
|
||||
import io.izzel.taboolib.client.TabooLibServer;
|
||||
import io.izzel.taboolib.client.packet.Packet;
|
||||
import io.izzel.taboolib.client.packet.PacketType;
|
||||
import io.izzel.taboolib.client.packet.PacketValue;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-08-22 23:01
|
||||
*/
|
||||
@PacketType(name = "command")
|
||||
public class PacketCommand extends Packet {
|
||||
|
||||
@PacketValue
|
||||
private String command;
|
||||
|
||||
public PacketCommand(int port) {
|
||||
super(port);
|
||||
}
|
||||
|
||||
public PacketCommand(String command) {
|
||||
super(Bukkit.getPort());
|
||||
this.command = command;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readOnServer() {
|
||||
String[] args = command.split(" ");
|
||||
if (args[0].equalsIgnoreCase("online")) {
|
||||
TabooLibServer.sendPacket(new PacketMessage(0, "Online: " + TabooLibServer.getClient().size()));
|
||||
} else {
|
||||
TabooLibServer.sendPacket(new PacketMessage(0, "Invalid arguments."));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package io.izzel.taboolib.client.packet.impl;
|
||||
|
||||
import io.izzel.taboolib.client.packet.Packet;
|
||||
import io.izzel.taboolib.client.packet.PacketType;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-08-22 23:01
|
||||
*/
|
||||
@PacketType(name = "empty")
|
||||
public class PacketEmpty extends Packet {
|
||||
|
||||
public PacketEmpty(int port) {
|
||||
super(port);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readOnServer() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readOnClient() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package io.izzel.taboolib.client.packet.impl;
|
||||
|
||||
import io.izzel.taboolib.client.TabooLibClient;
|
||||
import io.izzel.taboolib.client.packet.Packet;
|
||||
import io.izzel.taboolib.client.packet.PacketType;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-08-22 23:01
|
||||
*/
|
||||
@PacketType(name = "heartbeat")
|
||||
public class PacketHeartbeat extends Packet {
|
||||
|
||||
public PacketHeartbeat(int port) {
|
||||
super(port);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readOnServer() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readOnClient() {
|
||||
// 更新响应时间
|
||||
TabooLibClient.setLatestResponse(System.currentTimeMillis());
|
||||
// 回应服务端
|
||||
TabooLibClient.sendPacket(new PacketAlive(TabooLibClient.getSocket().getLocalPort()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package io.izzel.taboolib.client.packet.impl;
|
||||
|
||||
import io.izzel.taboolib.client.TabooLibServer;
|
||||
import io.izzel.taboolib.client.packet.Packet;
|
||||
import io.izzel.taboolib.client.packet.PacketType;
|
||||
import io.izzel.taboolib.module.locale.TLocale;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-08-22 23:38
|
||||
*/
|
||||
@PacketType(name = "join")
|
||||
public class PacketJoin extends Packet {
|
||||
|
||||
public PacketJoin(int port) {
|
||||
super(port);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readOnServer() {
|
||||
TabooLibServer.println("Client " + getPort() + " joined Communication Area.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readOnClient() {
|
||||
TLocale.sendToConsole("COMMUNICATION.CLIENT-JOINED", String.valueOf(getPort()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package io.izzel.taboolib.client.packet.impl;
|
||||
|
||||
import io.izzel.taboolib.module.locale.TLocale;
|
||||
import io.izzel.taboolib.client.TabooLibServer;
|
||||
import io.izzel.taboolib.client.packet.Packet;
|
||||
import io.izzel.taboolib.client.packet.PacketType;
|
||||
import io.izzel.taboolib.client.packet.PacketValue;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-08-22 23:01
|
||||
*/
|
||||
@PacketType(name = "message")
|
||||
public class PacketMessage extends Packet {
|
||||
|
||||
@PacketValue
|
||||
private String message;
|
||||
|
||||
public PacketMessage(int port) {
|
||||
this(port, "none");
|
||||
}
|
||||
|
||||
public PacketMessage(int port, String message) {
|
||||
super(port);
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public PacketMessage(String message) {
|
||||
super(Bukkit.getPort());
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readOnServer() {
|
||||
TabooLibServer.println(getPort() + ": " + message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readOnClient() {
|
||||
TLocale.sendToConsole("COMMUNICATION.PACKET-MESSAGE", String.valueOf(getPort()), message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package io.izzel.taboolib.client.packet.impl;
|
||||
|
||||
import io.izzel.taboolib.client.TabooLibServer;
|
||||
import io.izzel.taboolib.client.packet.Packet;
|
||||
import io.izzel.taboolib.client.packet.PacketType;
|
||||
import io.izzel.taboolib.client.packet.PacketValue;
|
||||
import io.izzel.taboolib.module.locale.TLocale;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-08-22 23:38
|
||||
*/
|
||||
@PacketType(name = "quit")
|
||||
public class PacketQuit extends Packet {
|
||||
|
||||
@PacketValue
|
||||
private String message;
|
||||
|
||||
public PacketQuit(int port) {
|
||||
this(port, "connect closed.");
|
||||
}
|
||||
|
||||
public PacketQuit(int port, String message) {
|
||||
super(port);
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readOnServer() {
|
||||
TabooLibServer.getConnection(getPort()).ifPresent(connection -> {
|
||||
// 注销连接
|
||||
TabooLibServer.getClient().remove(connection.getKey());
|
||||
// 关闭连接
|
||||
try {
|
||||
connection.getValue().getSocket().close();
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
// 提示信息
|
||||
TabooLibServer.println("Client " + getPort() + " leaved Communication Area: " + message);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readOnClient() {
|
||||
TLocale.sendToConsole("COMMUNICATION.CLIENT-QUITED", String.valueOf(getPort()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package io.izzel.taboolib.client.server;
|
||||
|
||||
import io.izzel.taboolib.client.TabooLibServer;
|
||||
import io.izzel.taboolib.client.TabooLibSettings;
|
||||
import io.izzel.taboolib.client.packet.impl.PacketJoin;
|
||||
import io.izzel.taboolib.client.packet.impl.PacketQuit;
|
||||
import org.bukkit.util.NumberConversions;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.PrintWriter;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
|
||||
/**
|
||||
* @Author sky
|
||||
* @Since 2018-08-22 22:30
|
||||
*/
|
||||
public class ClientConnection implements Runnable {
|
||||
|
||||
private final Socket socket;
|
||||
private BufferedReader reader;
|
||||
private PrintWriter writer;
|
||||
private String latestPacket;
|
||||
private long latestResponse = System.currentTimeMillis();
|
||||
|
||||
public ClientConnection(Socket socket) {
|
||||
this.socket = socket;
|
||||
try {
|
||||
reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), TabooLibSettings.getCharset()));
|
||||
writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(), TabooLibSettings.getCharset()), true);
|
||||
TabooLibServer.sendPacket(new PacketJoin(socket.getPort()));
|
||||
} catch (Exception e) {
|
||||
TabooLibServer.println("Client joined failed: " + e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while ((latestPacket = reader.readLine()) != null) {
|
||||
TabooLibServer.sendPacket(latestPacket);
|
||||
}
|
||||
} catch (SocketException e) {
|
||||
/*
|
||||
连接丢失,客户端退出
|
||||
*/
|
||||
TabooLibServer.sendPacket(new PacketQuit(socket.getPort(), "SocketException: " + e.getMessage()));
|
||||
} catch (Exception e) {
|
||||
TabooLibServer.println("Client running failed: " + e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isAlive() {
|
||||
return System.currentTimeMillis() - latestResponse < NumberConversions.toInt(TabooLibSettings.getSettings().getProperty("channel.timeout"));
|
||||
}
|
||||
|
||||
// *********************************
|
||||
//
|
||||
// Getter and Setter
|
||||
//
|
||||
// *********************************
|
||||
|
||||
public Socket getSocket() {
|
||||
return socket;
|
||||
}
|
||||
|
||||
public BufferedReader getReader() {
|
||||
return reader;
|
||||
}
|
||||
|
||||
public PrintWriter getWriter() {
|
||||
return writer;
|
||||
}
|
||||
|
||||
public String getLatestPacket() {
|
||||
return latestPacket;
|
||||
}
|
||||
|
||||
public long getLatestResponse() {
|
||||
return latestResponse;
|
||||
}
|
||||
|
||||
public void setLatestResponse(long latestResponse) {
|
||||
this.latestResponse = latestResponse;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user