├── .gitignore
├── README.md
├── messaging-client
├── pom.xml
└── src
│ └── main
│ └── java
│ └── me
│ └── hp888
│ └── messenger
│ ├── MessengerClient.java
│ ├── api
│ ├── callback
│ │ ├── Callback.java
│ │ └── CallbackManager.java
│ ├── client
│ │ └── Client.java
│ └── packet
│ │ ├── CallbackPacket.java
│ │ ├── Packet.java
│ │ ├── PacketHandler.java
│ │ └── PacketHandlerManager.java
│ ├── connection
│ └── SocketConnection.java
│ ├── packet
│ └── HeartbeatPacket.java
│ ├── thread
│ └── PacketReaderThread.java
│ └── util
│ └── SerializeUtil.java
├── messaging-server
├── pom.xml
└── src
│ └── main
│ └── java
│ └── me
│ └── hp888
│ └── messenger
│ ├── Bootstrap.java
│ ├── MessengerServer.java
│ ├── client
│ ├── Client.java
│ └── ClientManager.java
│ ├── thread
│ ├── PacketReaderThread.java
│ ├── PacketWriterThread.java
│ └── ServerShutdownThread.java
│ └── util
│ └── ThreadUtil.java
├── messenger-plugin
├── pom.xml
└── src
│ └── main
│ ├── java
│ └── me
│ │ └── hp888
│ │ └── messenger
│ │ ├── bukkit
│ │ └── BukkitMessengerPlugin.java
│ │ ├── bungee
│ │ └── BungeeMessengerPlugin.java
│ │ ├── shared
│ │ ├── Messenger.java
│ │ ├── MessengerPlugin.java
│ │ └── config
│ │ │ └── Configuration.java
│ │ └── velocity
│ │ └── VelocityMessengerPlugin.java
│ └── resources
│ ├── bungee.yml
│ ├── config.json
│ └── plugin.yml
└── pom.xml
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by .ignore support plugin (hsz.mobi)
2 | ### Java template
3 | # Compiled class file
4 | *.class
5 |
6 | # Log file
7 | *.log
8 |
9 | # BlueJ files
10 | *.ctxt
11 |
12 | # Mobile Tools for Java (J2ME)
13 | .mtj.tmp/
14 |
15 | # Package Files #
16 | *.jar
17 | *.war
18 | *.nar
19 | *.ear
20 | *.zip
21 | *.tar.gz
22 | *.rar
23 | *.iml
24 |
25 | target/
26 |
27 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
28 | hs_err_pid*
29 |
30 | .idea/*
31 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # messaging-system
2 |
3 | Packet-based messaging system.
4 |
5 | # Examples
6 |
7 | **How to run server?**
8 |
9 | You can specify port and host in java arguments for example:
10 | java -Dhost=0.0.0.0 -Dport=9999 -jar messaging-server-1.0-SNAPSHOT.jar
11 |
12 | or just run application:
13 | java -jar messaging-server-1.0-SNAPSHOT.jar
14 |
15 | # Using as API
16 |
17 | Add this code to your pom.xml file.
18 |
19 | ```xml
20 |
21 |
22 | safemc-repository
23 | https://safemc.pl/repository/releases
24 |
25 |
26 | ```
27 |
28 | And if you want to create your own MessengerClient implementation:
29 |
30 | ```xml
31 |
32 |
33 | me.hp888
34 | messaging-client
35 | 1.1-SNAPSHOT
36 |
37 |
38 | ```
39 |
40 | or if you want to use our plugin for bukkit/velocity/bungee:
41 |
42 | ```xml
43 |
44 |
45 | me.hp888
46 | messenger-plugin
47 | 1.1-SNAPSHOT
48 |
49 |
50 | ```
51 |
52 | **Example packet**
53 |
54 | ```java
55 | public final class ExamplePacket implements Packet {
56 |
57 | private String text;
58 |
59 | public ExamplePacket() {
60 | }
61 |
62 | public ExamplePacket(String text) {
63 | this.text = text;
64 | }
65 |
66 | public String getText() {
67 | return text;
68 | }
69 |
70 | public void setText(String text) {
71 | this.text = text;
72 | }
73 |
74 | @Override
75 | public void processPacket(PacketHandler handler) {
76 | if (!(handler instanceof ExamplePacketHandler)) {
77 | return;
78 | }
79 |
80 | ((ExamplePacketHandler) handler).handlePacket(this);
81 | }
82 |
83 | }
84 | ```
85 |
86 | **Example packet handler**
87 |
88 | ```java
89 | public final class ExamplePacketHandler implements PacketHandler {
90 |
91 | private final Client client;
92 |
93 | public ExamplePacketHandler(Client client) {
94 | this.client = client;
95 | }
96 |
97 | public void handlePacket(ExamplePacket packet) {
98 | System.out.println("Message: " + packet.getText());
99 | }
100 |
101 | public void handlePacket(ExampleCallbackPacket packet) {
102 | if (packet.isResponse()) {
103 | return;
104 | }
105 |
106 | packet.setText("test");
107 | packet.setResponse();
108 |
109 | client.sendPacket(packet); // sending packet back to handle callback
110 | }
111 |
112 | }
113 | ```
114 |
115 | **Example CallbackPacket**
116 |
117 | ```java
118 | public final class ExampleCallbackPacket extends CallbackPacket {
119 |
120 | private String text;
121 |
122 | public ExampleCallbackPacket() {
123 | }
124 |
125 | public ExampleCallbackPacket(String text) {
126 | this.text = text;
127 | }
128 |
129 | public String getText() {
130 | return text;
131 | }
132 |
133 | public void setText(String text) {
134 | this.text = text;
135 | }
136 |
137 | @Override
138 | public void processPacket(PacketHandler handler) {
139 | if (!(handler instanceof ExamplePacketHandler)) {
140 | return;
141 | }
142 |
143 | ((ExamplePacketHandler) handler).handlePacket(this);
144 | }
145 |
146 | }
147 | ```
148 |
149 | **Example connection to server**
150 |
151 | ```java
152 | final Client client = new MessengerClient();
153 | client.connect(new InetSocketAddress("127.0.0.1", 9999));
154 | ```
155 |
156 | **Subscribing packets**
157 |
158 | How it works?
159 | Only subscribed packets can be fully readed by the client, so if you subscribe ExamplePacket and this packet will be sent by any client Packet#processPacket method will be called.
160 |
161 | ```java
162 | client.subscribePackets(ExamplePacket.class.getName());
163 | ```
164 |
165 | **Adding packet handlers**
166 |
167 | ```java
168 | client.addPacketHandler(new ExamplePacketHandler());
169 | ```
170 |
171 | **Removing packet handlers**
172 |
173 | ```java
174 | client.removePacketHandler(ExamplePacketHandler.class);
175 | ```
176 |
177 | **Sending packets**
178 |
179 | ```java
180 | client.sendPacket(new ExamplePacket("test"));
181 | ```
182 |
183 | **Sending packets with callback**
184 | ```java
185 | client.sendPacket(new ExampleCallbackPacket(), new Callback() {
186 | @Override
187 | public void done(ExampleCallbackPacket packet) {
188 | System.out.println("Response message: " + packet.getText());
189 | }
190 |
191 | @Override
192 | public void error(String message) {
193 | System.out.println("Error message: " + message);
194 | }
195 | });
196 | ```
197 |
--------------------------------------------------------------------------------
/messaging-client/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | messaging-system
7 | me.hp888
8 | 1.1-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | messaging-client
13 |
14 |
15 | 1.8
16 | 1.8
17 |
18 |
19 |
20 |
21 | de.ruedigermoeller
22 | fst
23 | 2.57
24 | compile
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/messaging-client/src/main/java/me/hp888/messenger/MessengerClient.java:
--------------------------------------------------------------------------------
1 | package me.hp888.messenger;
2 |
3 | import lombok.Getter;
4 | import me.hp888.messenger.api.callback.Callback;
5 | import me.hp888.messenger.api.callback.CallbackManager;
6 | import me.hp888.messenger.api.client.Client;
7 | import me.hp888.messenger.api.packet.Packet;
8 | import me.hp888.messenger.api.packet.PacketHandler;
9 | import me.hp888.messenger.api.packet.PacketHandlerManager;
10 | import me.hp888.messenger.connection.SocketConnection;
11 | import me.hp888.messenger.packet.HeartbeatPacket;
12 | import me.hp888.messenger.thread.PacketReaderThread;
13 | import java.io.IOException;
14 | import java.net.InetSocketAddress;
15 | import java.net.Socket;
16 | import java.util.Collection;
17 | import java.util.Objects;
18 | import java.util.concurrent.ExecutorService;
19 | import java.util.concurrent.Executors;
20 | import java.util.concurrent.TimeUnit;
21 | import java.util.logging.Level;
22 | import java.util.logging.Logger;
23 |
24 | /**
25 | * @author hp888 on 07.11.2020.
26 | */
27 |
28 | public final class MessengerClient implements Client {
29 |
30 | private static final ExecutorService PACKET_SEND_EXECUTOR = Executors.newSingleThreadExecutor();
31 |
32 | private final PacketHandlerManager packetHandlers = new PacketHandlerManager();
33 | private final CallbackManager callbacks = new CallbackManager();
34 |
35 | @Getter
36 | private final ExecutorService packetHandleExecutor;
37 |
38 | public MessengerClient() {
39 | this(Runtime.getRuntime().availableProcessors() * 2);
40 | }
41 |
42 | public MessengerClient(int handlerPoolSize) {
43 | packetHandleExecutor = Executors.newFixedThreadPool(handlerPoolSize);
44 | }
45 |
46 | @Getter
47 | private SocketConnection connection;
48 |
49 | private boolean startedKeepAliveTask;
50 |
51 | @Override
52 | public void disconnect() throws IOException {
53 | if (Objects.isNull(connection) || !connection.isAlive()) {
54 | return;
55 | }
56 |
57 | connection.getSocket().close();
58 | }
59 |
60 | @Override
61 | public void connect(InetSocketAddress address) throws IOException {
62 | final Socket socket = new Socket();
63 | socket.setTcpNoDelay(true);
64 | socket.connect(address, 5000);
65 |
66 | connection = new SocketConnection(socket);
67 | new PacketReaderThread(this)
68 | .start();
69 |
70 | if (startedKeepAliveTask) {
71 | return;
72 | }
73 |
74 | startedKeepAliveTask = true;
75 |
76 | final Packet heartbeatPacket = new HeartbeatPacket();
77 | Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(() -> sendPacket(heartbeatPacket), 1L, 1L, TimeUnit.SECONDS);
78 | }
79 |
80 | @Override
81 | public void unsubscribePackets() {
82 | packetHandlers.unsubscribePackets();
83 | }
84 |
85 | @Override
86 | public void subscribePackets(String... classNames) {
87 | packetHandlers.subscribePackets(classNames);
88 | }
89 |
90 | @Override
91 | public boolean isPacketSubscribed(String name) {
92 | return packetHandlers.isPacketSubscribed(name);
93 | }
94 |
95 | @Override
96 | public Collection getPacketHandlers() {
97 | return packetHandlers.getPacketHandlers();
98 | }
99 |
100 | @Override
101 | public void addPacketHandler(PacketHandler handler) {
102 | packetHandlers.addPacketHandler(handler);
103 | }
104 |
105 | @Override
106 | public void removePacketHandler(Class extends PacketHandler> handlerClass) {
107 | packetHandlers.removePacketHandler(handlerClass);
108 | }
109 |
110 | @Override
111 | public Callback> getCallback(long id) {
112 | return callbacks.getCallback(id);
113 | }
114 |
115 | @Override
116 | public void sendPacket(Packet packet) {
117 | if (!checkConnection()) {
118 | return;
119 | }
120 |
121 | PACKET_SEND_EXECUTOR.execute(() -> {
122 | try {
123 | connection.sendPacket(packet, null);
124 | } catch (IOException ex) {
125 | Logger.getLogger(MessengerClient.class.getSimpleName())
126 | .log(Level.SEVERE, "Cannot send packet " + packet.getClass().getSimpleName(), ex);
127 |
128 | try {
129 | disconnect();
130 | } catch (IOException ignored) {}
131 | }
132 | });
133 | }
134 |
135 | @Override
136 | public void sendPacket(Packet packet, Callback callback) {
137 | if (Objects.isNull(callback)) {
138 | sendPacket(packet);
139 | return;
140 | }
141 |
142 | if (!checkConnection()) {
143 | return;
144 | }
145 |
146 | PACKET_SEND_EXECUTOR.execute(() -> {
147 | try {
148 | connection.sendPacket(packet, callbacks.addCallback(callback));
149 | } catch (IOException ex) {
150 | Logger.getLogger(MessengerClient.class.getSimpleName())
151 | .log(Level.SEVERE, "Cannot send packet " + packet.getClass().getSimpleName(), ex);
152 |
153 | try {
154 | disconnect();
155 | } catch (IOException ignored) {}
156 | }
157 | });
158 | }
159 |
160 | private boolean checkConnection() {
161 | if (Objects.isNull(connection) || !connection.isAlive()) {
162 | Logger.getLogger(getClass().getSimpleName())
163 | .warning("Cannot send packet when client is not connected!");
164 |
165 | return false;
166 | }
167 |
168 | return true;
169 | }
170 |
171 | }
--------------------------------------------------------------------------------
/messaging-client/src/main/java/me/hp888/messenger/api/callback/Callback.java:
--------------------------------------------------------------------------------
1 | package me.hp888.messenger.api.callback;
2 |
3 | import me.hp888.messenger.api.packet.Packet;
4 |
5 | /**
6 | * @author hp888 on 07.11.2020.
7 | */
8 |
9 | public interface Callback {
10 |
11 | void done(T packet);
12 |
13 | void error(String message);
14 |
15 | }
--------------------------------------------------------------------------------
/messaging-client/src/main/java/me/hp888/messenger/api/callback/CallbackManager.java:
--------------------------------------------------------------------------------
1 | package me.hp888.messenger.api.callback;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 | import java.util.concurrent.ThreadLocalRandom;
6 |
7 | /**
8 | * @author hp888 on 07.11.2020.
9 | */
10 |
11 | public final class CallbackManager {
12 |
13 | private final Map> callbackMap = new HashMap<>();
14 |
15 | public long addCallback(Callback> callback) {
16 | long id;
17 |
18 | do {
19 | id = ThreadLocalRandom.current().nextLong(Long.MIN_VALUE, Long.MAX_VALUE);
20 | } while (callbackMap.containsKey(id));
21 |
22 | callbackMap.put(id, callback);
23 | return id;
24 | }
25 |
26 | public Callback> getCallback(long id) {
27 | return callbackMap.remove(id);
28 | }
29 |
30 | }
--------------------------------------------------------------------------------
/messaging-client/src/main/java/me/hp888/messenger/api/client/Client.java:
--------------------------------------------------------------------------------
1 | package me.hp888.messenger.api.client;
2 |
3 | import me.hp888.messenger.api.callback.Callback;
4 | import me.hp888.messenger.api.packet.Packet;
5 | import me.hp888.messenger.api.packet.PacketHandler;
6 | import me.hp888.messenger.connection.SocketConnection;
7 | import java.io.IOException;
8 | import java.net.InetSocketAddress;
9 | import java.util.Collection;
10 | import java.util.concurrent.ExecutorService;
11 |
12 | /**
13 | * @author hp888 on 07.11.2020.
14 | */
15 |
16 | public interface Client {
17 |
18 | SocketConnection getConnection();
19 |
20 | ExecutorService getPacketHandleExecutor();
21 |
22 | /* connection */
23 |
24 | void disconnect() throws IOException;
25 |
26 | void connect(InetSocketAddress address) throws IOException;
27 |
28 | /* packet subscription */
29 |
30 | void unsubscribePackets();
31 |
32 | void subscribePackets(String... classNames);
33 |
34 | boolean isPacketSubscribed(String className);
35 |
36 | /* packet handlers */
37 |
38 | Collection getPacketHandlers();
39 |
40 | void addPacketHandler(PacketHandler handler);
41 |
42 | void removePacketHandler(Class extends PacketHandler> handlerClass);
43 |
44 | /* callbacks */
45 |
46 | Callback> getCallback(long id);
47 |
48 | /* sending packets */
49 |
50 | void sendPacket(Packet packet) throws IOException;
51 |
52 | void sendPacket(Packet packet, Callback callback) throws IOException;
53 |
54 | }
--------------------------------------------------------------------------------
/messaging-client/src/main/java/me/hp888/messenger/api/packet/CallbackPacket.java:
--------------------------------------------------------------------------------
1 | package me.hp888.messenger.api.packet;
2 |
3 | import lombok.Getter;
4 | import lombok.Setter;
5 | import java.util.Objects;
6 |
7 | /**
8 | * @author hp888 on 08.11.2020.
9 | */
10 |
11 | @Getter
12 | public abstract class CallbackPacket implements Packet {
13 |
14 | @Setter
15 | private long callbackId;
16 | private boolean response;
17 | private String errorMessage;
18 |
19 | public void setResponse() {
20 | this.response = true;
21 | }
22 |
23 | public boolean isSuccess() {
24 | return Objects.isNull(errorMessage);
25 | }
26 |
27 | public void setErrorMessage(String errorMessage) {
28 | this.errorMessage = errorMessage;
29 | }
30 |
31 | }
--------------------------------------------------------------------------------
/messaging-client/src/main/java/me/hp888/messenger/api/packet/Packet.java:
--------------------------------------------------------------------------------
1 | package me.hp888.messenger.api.packet;
2 |
3 | import me.hp888.messenger.util.SerializeUtil;
4 | import java.io.ByteArrayOutputStream;
5 | import java.io.DataOutputStream;
6 | import java.io.IOException;
7 | import java.io.Serializable;
8 | import java.nio.charset.StandardCharsets;
9 |
10 | /**
11 | * @author hp888 on 07.11.2020.
12 | */
13 |
14 | public interface Packet extends Serializable {
15 |
16 | default byte[] serialize() throws IOException {
17 | final byte[] packetData = SerializeUtil.serializeObject(this);
18 | final byte[] className = getClass().getName().getBytes(StandardCharsets.UTF_8);
19 |
20 | final int bufferSize = className.length + packetData.length + 8; // two ints are stored in 8 bytes
21 |
22 | try (final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(bufferSize); final DataOutputStream dataOutputStream = new DataOutputStream(byteArrayOutputStream)) {
23 | dataOutputStream.writeInt(className.length);
24 | dataOutputStream.write(className);
25 |
26 | dataOutputStream.writeInt(packetData.length);
27 | dataOutputStream.write(packetData);
28 |
29 | return byteArrayOutputStream.toByteArray();
30 | }
31 | }
32 |
33 | default void processPacket(PacketHandler handler) {}
34 |
35 | }
--------------------------------------------------------------------------------
/messaging-client/src/main/java/me/hp888/messenger/api/packet/PacketHandler.java:
--------------------------------------------------------------------------------
1 | package me.hp888.messenger.api.packet;
2 |
3 | /**
4 | * @author hp888 on 07.11.2020.
5 | */
6 |
7 | public interface PacketHandler {
8 |
9 | }
--------------------------------------------------------------------------------
/messaging-client/src/main/java/me/hp888/messenger/api/packet/PacketHandlerManager.java:
--------------------------------------------------------------------------------
1 | package me.hp888.messenger.api.packet;
2 |
3 | import java.util.*;
4 |
5 | /**
6 | * @author hp888 on 07.11.2020.
7 | */
8 |
9 | public final class PacketHandlerManager {
10 |
11 | private final Set subscribedPackets = new HashSet<>();
12 | private final Set handlers = new HashSet<>();
13 |
14 | public void subscribePackets(String... classNames) {
15 | subscribedPackets.addAll(Arrays.asList(classNames));
16 | }
17 |
18 | public boolean isPacketSubscribed(String className) {
19 | return subscribedPackets.contains(className);
20 | }
21 |
22 | public void unsubscribePackets() {
23 | subscribedPackets.clear();
24 | }
25 |
26 | public Collection getPacketHandlers() {
27 | return handlers;
28 | }
29 |
30 | public void removePacketHandler(Class extends PacketHandler> handlerClass) {
31 | handlers.removeIf(handler -> handler.getClass().equals(handlerClass));
32 | }
33 |
34 | public void addPacketHandler(PacketHandler handler) {
35 | handlers.add(handler);
36 | }
37 |
38 | }
--------------------------------------------------------------------------------
/messaging-client/src/main/java/me/hp888/messenger/connection/SocketConnection.java:
--------------------------------------------------------------------------------
1 | package me.hp888.messenger.connection;
2 |
3 | import lombok.Getter;
4 | import me.hp888.messenger.api.packet.CallbackPacket;
5 | import me.hp888.messenger.api.packet.Packet;
6 | import java.io.ByteArrayOutputStream;
7 | import java.io.DataInputStream;
8 | import java.io.DataOutputStream;
9 | import java.io.IOException;
10 | import java.net.Socket;
11 | import java.util.Objects;
12 |
13 | /**
14 | * @author hp888 on 08.11.2020.
15 | */
16 |
17 | @Getter
18 | public final class SocketConnection {
19 |
20 | private final Socket socket;
21 |
22 | private final DataInputStream inputStream;
23 | private final DataOutputStream outputStream;
24 |
25 | public SocketConnection(Socket socket) throws IOException {
26 | this.socket = socket;
27 | this.inputStream = new DataInputStream(socket.getInputStream());
28 | this.outputStream = new DataOutputStream(socket.getOutputStream());
29 | }
30 |
31 | public void sendPacket(Packet packet, Long callbackId) throws IOException {
32 | if (packet instanceof CallbackPacket && Objects.nonNull(callbackId)) {
33 | ((CallbackPacket) packet).setCallbackId(callbackId);
34 | }
35 |
36 | final byte[] serializedPacket = packet.serialize();
37 | try (final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); final DataOutputStream dataOutputStream = new DataOutputStream(byteArrayOutputStream)) {
38 | dataOutputStream.writeInt(serializedPacket.length);
39 | dataOutputStream.write(serializedPacket);
40 | dataOutputStream.flush();
41 |
42 | outputStream.write(byteArrayOutputStream.toByteArray());
43 | outputStream.flush();
44 | }
45 | }
46 |
47 | public boolean isAlive() {
48 | return socket.isConnected() && !socket.isClosed();
49 | }
50 |
51 | }
--------------------------------------------------------------------------------
/messaging-client/src/main/java/me/hp888/messenger/packet/HeartbeatPacket.java:
--------------------------------------------------------------------------------
1 | package me.hp888.messenger.packet;
2 |
3 | import lombok.ToString;
4 | import me.hp888.messenger.api.packet.Packet;
5 |
6 | /**
7 | * @author hp888 on 08.11.2020.
8 | */
9 |
10 | @ToString
11 | public final class HeartbeatPacket implements Packet {
12 |
13 | }
--------------------------------------------------------------------------------
/messaging-client/src/main/java/me/hp888/messenger/thread/PacketReaderThread.java:
--------------------------------------------------------------------------------
1 | package me.hp888.messenger.thread;
2 |
3 | import me.hp888.messenger.api.callback.Callback;
4 | import me.hp888.messenger.api.client.Client;
5 | import me.hp888.messenger.api.packet.CallbackPacket;
6 | import me.hp888.messenger.api.packet.Packet;
7 | import me.hp888.messenger.connection.SocketConnection;
8 | import me.hp888.messenger.util.SerializeUtil;
9 | import java.io.ByteArrayInputStream;
10 | import java.io.DataInputStream;
11 | import java.io.IOException;
12 | import java.nio.charset.StandardCharsets;
13 | import java.util.Objects;
14 |
15 | /**
16 | * @author hp888 on 08.11.2020.
17 | */
18 |
19 | public final class PacketReaderThread extends Thread {
20 |
21 | private final Client client;
22 |
23 | public PacketReaderThread(Client client) {
24 | super("Messenger PacketReaderThread");
25 | this.client = client;
26 | }
27 |
28 | @Override
29 | public void run() {
30 | final SocketConnection connection = client.getConnection();
31 | final DataInputStream inputStream = connection.getInputStream();
32 |
33 | try {
34 | while (connection.isAlive()) {
35 | final int wholePacketSize = inputStream.readInt();
36 | final byte[] wholePacketData = new byte[wholePacketSize];
37 | inputStream.readFully(wholePacketData);
38 |
39 | final DataInputStream packetStream = new DataInputStream(new ByteArrayInputStream(wholePacketData));
40 | final int classNameLength = packetStream.readInt();
41 | final byte[] className = new byte[classNameLength];
42 | packetStream.readFully(className);
43 |
44 | final int packetSize = packetStream.readInt();
45 | if (!client.isPacketSubscribed(new String(className, StandardCharsets.UTF_8))) {
46 | packetStream.skipBytes(packetSize);
47 | continue;
48 | }
49 |
50 | final byte[] packetData = new byte[packetSize];
51 | packetStream.readFully(packetData);
52 |
53 | if (packetData.length == 0) {
54 | continue;
55 | }
56 |
57 | client.getPacketHandleExecutor().execute(() -> {
58 | final Packet packet = SerializeUtil.deserializeObject(packetData);
59 | if (handleCallback(packet)) {
60 | return;
61 | }
62 |
63 | client.getPacketHandlers()
64 | .forEach(packet::processPacket);
65 | });
66 | }
67 | } catch (IOException ex) {
68 | System.out.println("[INFO] Disconnected from messenger! Cause: " + ex.toString());
69 | ex.printStackTrace();
70 | }
71 |
72 | throw new ThreadDeath();
73 | }
74 |
75 | @SuppressWarnings("unchecked")
76 | private boolean handleCallback(Packet packet) {
77 | if (packet instanceof CallbackPacket) {
78 | final CallbackPacket callbackPacket = (CallbackPacket) packet;
79 | if (callbackPacket.getCallbackId() != 0L && callbackPacket.isResponse()) {
80 | final Callback callback = client.getCallback(callbackPacket.getCallbackId());
81 | if (Objects.nonNull(callback)) {
82 | if (callbackPacket.isSuccess()) {
83 | callback.done(callbackPacket);
84 | } else {
85 | callback.error(callbackPacket.getErrorMessage());
86 | }
87 | }
88 |
89 | return true;
90 | }
91 | }
92 |
93 | return false;
94 | }
95 |
96 | }
--------------------------------------------------------------------------------
/messaging-client/src/main/java/me/hp888/messenger/util/SerializeUtil.java:
--------------------------------------------------------------------------------
1 | package me.hp888.messenger.util;
2 |
3 | import org.nustaq.serialization.FSTConfiguration;
4 |
5 | /**
6 | * @author hp888 on 07.11.2020.
7 | */
8 |
9 | public final class SerializeUtil {
10 |
11 | private static final FSTConfiguration FAST_SERIALIZER = FSTConfiguration.createDefaultConfiguration();
12 |
13 | private SerializeUtil() {}
14 |
15 | public static byte[] serializeObject(Object object) {
16 | return FAST_SERIALIZER.asByteArray(object);
17 | }
18 |
19 | @SuppressWarnings("unchecked")
20 | public static T deserializeObject(byte[] data) {
21 | return (T) FAST_SERIALIZER.asObject(data);
22 | }
23 |
24 | }
--------------------------------------------------------------------------------
/messaging-server/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | messaging-system
7 | me.hp888
8 | 1.1-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | messaging-server
13 |
14 |
15 | 1.8
16 | 1.8
17 |
18 |
19 |
20 | clean install
21 |
22 |
23 | org.apache.maven.plugins
24 | maven-jar-plugin
25 | 3.2.0
26 |
27 |
28 |
29 | true
30 | me.hp888.messenger.Bootstrap
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/messaging-server/src/main/java/me/hp888/messenger/Bootstrap.java:
--------------------------------------------------------------------------------
1 | package me.hp888.messenger;
2 |
3 | /**
4 | * @author hp888 on 07.11.2020.
5 | */
6 |
7 | public final class Bootstrap {
8 |
9 | public static void main(String[] args) {
10 | final Thread thread = new Thread(MessengerServer.getInstance()::start);
11 | thread.setName("Server thread");
12 | thread.start();
13 | }
14 |
15 | }
--------------------------------------------------------------------------------
/messaging-server/src/main/java/me/hp888/messenger/MessengerServer.java:
--------------------------------------------------------------------------------
1 | package me.hp888.messenger;
2 |
3 | import lombok.Getter;
4 | import lombok.Setter;
5 | import me.hp888.messenger.client.Client;
6 | import me.hp888.messenger.client.ClientManager;
7 | import me.hp888.messenger.thread.PacketWriterThread;
8 | import me.hp888.messenger.thread.ServerShutdownThread;
9 | import java.io.IOException;
10 | import java.net.InetSocketAddress;
11 | import java.net.ServerSocket;
12 | import java.net.Socket;
13 | import java.util.logging.Level;
14 | import java.util.logging.Logger;
15 |
16 | /**
17 | * @author hp888 on 07.11.2020.
18 | */
19 |
20 | @Getter
21 | @Setter
22 | public final class MessengerServer {
23 |
24 | @Getter
25 | private static final MessengerServer instance = new MessengerServer();
26 |
27 | private final Logger logger = Logger.getLogger(MessengerServer.class.getSimpleName());
28 | private final ClientManager clientManager = new ClientManager(this);
29 |
30 | private boolean running;
31 |
32 | void start() {
33 | running = true;
34 |
35 | startThreads();
36 | startServer();
37 | }
38 |
39 | private void startThreads() {
40 | new PacketWriterThread(this).start();
41 | Runtime.getRuntime().addShutdownHook(new ServerShutdownThread(this));
42 | }
43 |
44 | private void startServer() {
45 | final ServerSocket serverSocket;
46 |
47 | try {
48 | serverSocket = new ServerSocket();
49 | serverSocket.bind(new InetSocketAddress(System.getProperty("host", "127.0.0.1"), Integer.parseInt(System.getProperty("port", "9999"))));
50 | serverSocket.setSoTimeout(10000);
51 | } catch (IOException ex) {
52 | logger.log(Level.SEVERE, "Cannot bind server on " + System.getProperty("host", "127.0.0.1") + ":" + System.getProperty("port", "9999") + ", probably used by other application?", ex);
53 | return;
54 | }
55 |
56 | logger.info("Server bound on " + serverSocket.getInetAddress().toString());
57 |
58 | while (!serverSocket.isClosed()) {
59 | final Socket socket;
60 |
61 | try {
62 | socket = serverSocket.accept();
63 | } catch (IOException ex) {
64 | if (ex.getMessage().equals("Accept timed out")) {
65 | continue;
66 | }
67 |
68 | logger.log(Level.SEVERE, "Cannot accept new connection!", ex);
69 | continue;
70 | }
71 |
72 | try {
73 | clientManager.addClient(new Client(socket));
74 | } catch (IOException ex) {
75 | logger.log(Level.SEVERE, "Cannot get I/O stream from recently accepted connection!");
76 | }
77 |
78 | }
79 |
80 | }
81 |
82 | }
--------------------------------------------------------------------------------
/messaging-server/src/main/java/me/hp888/messenger/client/Client.java:
--------------------------------------------------------------------------------
1 | package me.hp888.messenger.client;
2 |
3 | import lombok.Data;
4 | import java.io.ByteArrayOutputStream;
5 | import java.io.DataInputStream;
6 | import java.io.DataOutputStream;
7 | import java.io.IOException;
8 | import java.net.InetAddress;
9 | import java.net.Socket;
10 | import java.util.Queue;
11 | import java.util.concurrent.ConcurrentLinkedQueue;
12 |
13 | /**
14 | * @author hp888 on 07.11.2020.
15 | */
16 |
17 | @Data
18 | public final class Client {
19 |
20 | private final Socket socket;
21 | private final InetAddress address;
22 |
23 | private final DataInputStream inputStream;
24 | private final DataOutputStream outputStream;
25 |
26 | public Client(Socket socket) throws IOException {
27 | this.socket = socket;
28 | this.address = socket.getInetAddress();
29 | this.inputStream = new DataInputStream(socket.getInputStream());
30 | this.outputStream = new DataOutputStream(socket.getOutputStream());
31 | }
32 |
33 | private final Queue outgoingPackets = new ConcurrentLinkedQueue<>();
34 |
35 | void sendPacket(byte[] bytes) throws IOException {
36 | final int bufferSize = bytes.length + 4; // single int value is stored in 4 bytes
37 | try (final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(bufferSize); final DataOutputStream dataOutputStream = new DataOutputStream(byteArrayOutputStream)) {
38 | dataOutputStream.writeInt(bytes.length);
39 | dataOutputStream.write(bytes, 0, bytes.length);
40 | dataOutputStream.flush();
41 |
42 | outputStream.write(byteArrayOutputStream.toByteArray());
43 | outputStream.flush();
44 | }
45 | }
46 |
47 | public boolean isConnected() {
48 | return socket.isConnected() && !socket.isClosed();
49 | }
50 |
51 | }
--------------------------------------------------------------------------------
/messaging-server/src/main/java/me/hp888/messenger/client/ClientManager.java:
--------------------------------------------------------------------------------
1 | package me.hp888.messenger.client;
2 |
3 | import lombok.Getter;
4 | import lombok.RequiredArgsConstructor;
5 | import me.hp888.messenger.MessengerServer;
6 | import me.hp888.messenger.thread.PacketReaderThread;
7 | import java.io.IOException;
8 | import java.util.Collections;
9 | import java.util.Set;
10 | import java.util.concurrent.ConcurrentHashMap;
11 | import java.util.concurrent.atomic.AtomicInteger;
12 | import java.util.logging.Level;
13 |
14 | /**
15 | * @author hp888 on 07.11.2020.
16 | */
17 |
18 | @Getter
19 | @RequiredArgsConstructor
20 | public final class ClientManager {
21 |
22 | private final MessengerServer server;
23 | private final Set clients = Collections.newSetFromMap(new ConcurrentHashMap<>());
24 |
25 | private final AtomicInteger threadCounter = new AtomicInteger();
26 |
27 | public void addClient(Client client) {
28 | clients.add(client);
29 | threadCounter.incrementAndGet();
30 | server.getLogger().info("Client has connected to the server! [" + client.getAddress().toString() + "]");
31 |
32 | new PacketReaderThread(server, client)
33 | .start();
34 | }
35 |
36 | public void removeClient(Client client) {
37 | clients.remove(client);
38 | threadCounter.decrementAndGet();
39 | server.getLogger().info("Client has disconnected from the server! [" + client.getAddress().toString() + "]");
40 | }
41 |
42 | public void sendPacket(byte[] packet) {
43 | clients.forEach(client -> {
44 | try {
45 | client.sendPacket(packet);
46 | } catch (IOException ex) {
47 | server.getLogger().log(Level.SEVERE, "Cannot send packet to client!", ex);
48 | removeClient(client);
49 | }
50 | });
51 | }
52 |
53 | }
--------------------------------------------------------------------------------
/messaging-server/src/main/java/me/hp888/messenger/thread/PacketReaderThread.java:
--------------------------------------------------------------------------------
1 | package me.hp888.messenger.thread;
2 |
3 | import me.hp888.messenger.MessengerServer;
4 | import me.hp888.messenger.client.Client;
5 | import java.io.DataInputStream;
6 | import java.io.EOFException;
7 | import java.util.Objects;
8 | import java.util.logging.Level;
9 |
10 | /**
11 | * @author hp888 on 07.11.2020.
12 | */
13 |
14 | public final class PacketReaderThread extends Thread {
15 |
16 | private final MessengerServer server;
17 | private final Client client;
18 |
19 | public PacketReaderThread(MessengerServer server, Client client) {
20 | super("Messenger Packet Reader Thread #" + server.getClientManager().getThreadCounter().get());
21 | this.server = server;
22 | this.client = client;
23 | }
24 |
25 | @Override
26 | public void run() {
27 | final DataInputStream inputStream = client.getInputStream();
28 |
29 | try {
30 | while (client.isConnected()) {
31 | final byte[] bytes = new byte[inputStream.readInt()];
32 | inputStream.readFully(bytes);
33 |
34 | client.getOutgoingPackets().add(bytes);
35 | }
36 | } catch (Exception ex) {
37 | if (!(ex instanceof EOFException) && (Objects.isNull(ex.getMessage()) || !ex.getMessage().equals("Connection reset"))) {
38 | server.getLogger().log(Level.SEVERE, "Cannot read packet!", ex);
39 | }
40 |
41 | server.getClientManager().removeClient(client);
42 | }
43 | }
44 |
45 | }
--------------------------------------------------------------------------------
/messaging-server/src/main/java/me/hp888/messenger/thread/PacketWriterThread.java:
--------------------------------------------------------------------------------
1 | package me.hp888.messenger.thread;
2 |
3 | import me.hp888.messenger.MessengerServer;
4 | import me.hp888.messenger.util.ThreadUtil;
5 |
6 | /**
7 | * @author hp888 on 07.11.2020.
8 | */
9 |
10 | public final class PacketWriterThread extends Thread {
11 |
12 | private final MessengerServer server;
13 |
14 | public PacketWriterThread(MessengerServer server) {
15 | super("Messenger Packet Writer Thread");
16 | this.server = server;
17 | }
18 |
19 | @Override
20 | public void run() {
21 | while (server.isRunning()) {
22 | server.getClientManager().getClients().forEach(client -> {
23 | while (!client.getOutgoingPackets().isEmpty()) {
24 | server.getClientManager().sendPacket(client.getOutgoingPackets().poll());
25 | }
26 | });
27 |
28 | ThreadUtil.sleep(1L);
29 | }
30 | }
31 |
32 | }
--------------------------------------------------------------------------------
/messaging-server/src/main/java/me/hp888/messenger/thread/ServerShutdownThread.java:
--------------------------------------------------------------------------------
1 | package me.hp888.messenger.thread;
2 |
3 | import lombok.RequiredArgsConstructor;
4 | import me.hp888.messenger.MessengerServer;
5 |
6 | /**
7 | * @author hp888 on 09.11.2020.
8 | */
9 |
10 | @RequiredArgsConstructor
11 | public final class ServerShutdownThread extends Thread {
12 |
13 | private final MessengerServer server;
14 |
15 | @Override
16 | public void run() {
17 | server.getLogger().info("Shutting down server...");
18 | server.setRunning(false);
19 | }
20 |
21 | }
--------------------------------------------------------------------------------
/messaging-server/src/main/java/me/hp888/messenger/util/ThreadUtil.java:
--------------------------------------------------------------------------------
1 | package me.hp888.messenger.util;
2 |
3 | import me.hp888.messenger.MessengerServer;
4 | import java.util.logging.Level;
5 |
6 | /**
7 | * @author hp888 on 07.11.2020.
8 | */
9 |
10 | public final class ThreadUtil {
11 |
12 | private ThreadUtil() {}
13 |
14 | public static void sleep(long ms) {
15 | try {
16 | Thread.sleep(ms);
17 | } catch (InterruptedException ex) {
18 | MessengerServer.getInstance().getLogger().log(Level.SEVERE, "Cannot interrupt thread " + Thread.currentThread().getName() + "!", ex);
19 | Thread.currentThread().stop();
20 | }
21 | }
22 |
23 | }
--------------------------------------------------------------------------------
/messenger-plugin/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | messaging-system
7 | me.hp888
8 | 1.1-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | messenger-plugin
13 |
14 |
15 | 1.8
16 | 1.8
17 |
18 |
19 |
20 |
21 | bungeecord-repo
22 | https://oss.sonatype.org/content/repositories/snapshots
23 |
24 |
25 | spigot-repo
26 | https://hub.spigotmc.org/nexus/content/repositories/snapshots/
27 |
28 |
29 | velocity
30 | https://repo.velocitypowered.com/snapshots/
31 |
32 |
33 |
34 |
35 |
36 | org.spigotmc
37 | spigot-api
38 | 1.16.4-R0.1-SNAPSHOT
39 | provided
40 |
41 |
42 | net.md-5
43 | bungeecord-api
44 | 1.16-R0.4-SNAPSHOT
45 | jar
46 | provided
47 |
48 |
49 | com.velocitypowered
50 | velocity-api
51 | 1.0.0-SNAPSHOT
52 | provided
53 |
54 |
55 | me.hp888
56 | messaging-client
57 | 1.0-SNAPSHOT
58 | compile
59 |
60 |
61 | com.google.code.gson
62 | gson
63 | 2.8.5
64 | provided
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/messenger-plugin/src/main/java/me/hp888/messenger/bukkit/BukkitMessengerPlugin.java:
--------------------------------------------------------------------------------
1 | package me.hp888.messenger.bukkit;
2 |
3 | import me.hp888.messenger.MessengerClient;
4 | import me.hp888.messenger.api.client.Client;
5 | import me.hp888.messenger.shared.Messenger;
6 | import me.hp888.messenger.shared.MessengerPlugin;
7 | import me.hp888.messenger.shared.config.Configuration;
8 | import org.bukkit.plugin.java.JavaPlugin;
9 | import java.io.IOException;
10 | import java.io.File;
11 | import java.net.InetSocketAddress;
12 | import java.util.Objects;
13 | import java.util.logging.Level;
14 |
15 | /**
16 | * @author hp888 on 09.11.2020.
17 | */
18 |
19 | public final class BukkitMessengerPlugin extends JavaPlugin {
20 |
21 | private final Configuration configuration = new Configuration();
22 |
23 | @Override
24 | public void onEnable() {
25 | try {
26 | configuration.load(new File(getDataFolder(), "config.json"));
27 | } catch (IOException ex) {
28 | getLogger().log(Level.SEVERE, "Cannot load configuration!", ex);
29 | getServer().getPluginManager().disablePlugin(this);
30 | return;
31 | }
32 |
33 | final Configuration.Pool pool = configuration.getPool();
34 | final Client client;
35 |
36 | if (pool.isAdjustSizeAutomatically()) {
37 | client = new MessengerClient();
38 | } else {
39 | client = new MessengerClient(Math.max(2, pool.getSize()));
40 | }
41 |
42 | try {
43 | client.connect(new InetSocketAddress(configuration.getHost(), configuration.getPort()));
44 | } catch (IOException ex) {
45 | getLogger().log(Level.SEVERE, "Cannot connect to remote server!", ex);
46 | getServer().getPluginManager().disablePlugin(this);
47 | return;
48 | }
49 |
50 | Messenger.setInstance(new MessengerPlugin(client, getLogger()));
51 | }
52 |
53 | @Override
54 | public void onDisable() {
55 | final MessengerPlugin messenger = Messenger.getInstance();
56 | if (Objects.isNull(messenger)) {
57 | return;
58 | }
59 |
60 | try {
61 | messenger.disconnect();
62 | } catch (IOException ignored) {}
63 | }
64 | }
--------------------------------------------------------------------------------
/messenger-plugin/src/main/java/me/hp888/messenger/bungee/BungeeMessengerPlugin.java:
--------------------------------------------------------------------------------
1 | package me.hp888.messenger.bungee;
2 |
3 | import me.hp888.messenger.MessengerClient;
4 | import me.hp888.messenger.api.client.Client;
5 | import me.hp888.messenger.shared.Messenger;
6 | import me.hp888.messenger.shared.MessengerPlugin;
7 | import me.hp888.messenger.shared.config.Configuration;
8 | import net.md_5.bungee.api.plugin.Plugin;
9 | import java.io.File;
10 | import java.io.IOException;
11 | import java.net.InetSocketAddress;
12 | import java.util.Objects;
13 | import java.util.logging.Level;
14 |
15 | /**
16 | * @author hp888 on 09.11.2020.
17 | */
18 |
19 | public final class BungeeMessengerPlugin extends Plugin {
20 |
21 | private final Configuration configuration = new Configuration();
22 |
23 | @Override
24 | public void onEnable() {
25 | try {
26 | configuration.load(new File(getDataFolder(), "config.json"));
27 | } catch (IOException ex) {
28 | getLogger().log(Level.SEVERE, "Cannot load configuration!", ex);
29 | getProxy().stop();
30 | return;
31 | }
32 |
33 |
34 | final Configuration.Pool pool = configuration.getPool();
35 | final Client client;
36 |
37 | if (pool.isAdjustSizeAutomatically()) {
38 | client = new MessengerClient();
39 | } else {
40 | client = new MessengerClient(Math.max(2, pool.getSize()));
41 | }
42 |
43 | try {
44 | client.connect(new InetSocketAddress(configuration.getHost(), configuration.getPort()));
45 | } catch (IOException ex) {
46 | getLogger().log(Level.SEVERE, "Cannot connect to remote server!", ex);
47 | getProxy().stop();
48 | return;
49 | }
50 |
51 | Messenger.setInstance(new MessengerPlugin(client, getLogger()));
52 |
53 | }
54 |
55 | @Override
56 | public void onDisable() {
57 | final MessengerPlugin messenger = Messenger.getInstance();
58 | if (Objects.isNull(messenger)) {
59 | return;
60 | }
61 |
62 | try {
63 | messenger.disconnect();
64 | } catch (IOException ignored) {}
65 | }
66 |
67 | }
--------------------------------------------------------------------------------
/messenger-plugin/src/main/java/me/hp888/messenger/shared/Messenger.java:
--------------------------------------------------------------------------------
1 | package me.hp888.messenger.shared;
2 |
3 | import lombok.Getter;
4 | import lombok.Setter;
5 |
6 | /**
7 | * @author hp888 on 09.11.2020.
8 | */
9 |
10 | public final class Messenger {
11 |
12 | @Getter
13 | @Setter
14 | private static MessengerPlugin instance;
15 |
16 | private Messenger() {
17 | }
18 |
19 | }
--------------------------------------------------------------------------------
/messenger-plugin/src/main/java/me/hp888/messenger/shared/MessengerPlugin.java:
--------------------------------------------------------------------------------
1 | package me.hp888.messenger.shared;
2 |
3 | import lombok.RequiredArgsConstructor;
4 | import me.hp888.messenger.api.callback.Callback;
5 | import me.hp888.messenger.api.client.Client;
6 | import me.hp888.messenger.api.packet.Packet;
7 | import me.hp888.messenger.api.packet.PacketHandler;
8 | import java.io.IOException;
9 | import java.util.logging.Level;
10 | import java.util.logging.Logger;
11 |
12 | /**
13 | * @author hp888 on 09.11.2020.
14 | */
15 |
16 | @RequiredArgsConstructor
17 | public final class MessengerPlugin {
18 |
19 | private final Client client;
20 | private final Logger logger;
21 |
22 | /* packet sending */
23 |
24 | public void sendPacket(Packet packet) {
25 | try {
26 | client.sendPacket(packet);
27 | } catch (IOException ex) {
28 | logger.log(Level.SEVERE, "Cannot send packet \"" + packet.getClass().getSimpleName() + "\"!", ex);
29 | }
30 | }
31 |
32 | public void sendPacket(Packet packet, Callback> callback) {
33 | try {
34 | client.sendPacket(packet, callback);
35 | } catch (IOException ex) {
36 | logger.log(Level.SEVERE, "Cannot send packet \"" + packet.getClass().getSimpleName() + "\"!", ex);
37 | }
38 | }
39 |
40 | /* packet registering */
41 |
42 | public void unsubscribePackets() {
43 | client.unsubscribePackets();
44 | }
45 |
46 | public void subscribePackets(String... classNames) {
47 | client.subscribePackets(classNames);
48 | }
49 |
50 | /* packet handlers */
51 |
52 | public void addPacketHandler(PacketHandler handler) {
53 | client.addPacketHandler(handler);
54 | }
55 |
56 | public void removePacketHandler(Class extends PacketHandler> handlerClass) {
57 | client.removePacketHandler(handlerClass);
58 | }
59 |
60 | public void disconnect() throws IOException {
61 | client.disconnect();
62 | }
63 |
64 | }
--------------------------------------------------------------------------------
/messenger-plugin/src/main/java/me/hp888/messenger/shared/config/Configuration.java:
--------------------------------------------------------------------------------
1 | package me.hp888.messenger.shared.config;
2 |
3 | import com.google.gson.JsonObject;
4 | import com.google.gson.JsonParser;
5 | import lombok.Data;
6 | import lombok.Getter;
7 | import me.hp888.messenger.shared.Messenger;
8 | import java.io.File;
9 | import java.io.FileReader;
10 | import java.io.IOException;
11 | import java.nio.file.Files;
12 | import java.nio.file.StandardCopyOption;
13 | import java.util.Objects;
14 |
15 | /**
16 | * @author hp888 on 09.11.2020.
17 | */
18 |
19 | @Getter
20 | public final class Configuration {
21 |
22 | private String host;
23 | private Pool pool;
24 | private int port;
25 |
26 | public void load(File file) throws IOException {
27 | file.getParentFile().mkdirs();
28 |
29 | if (!file.exists()) {
30 | Files.copy(Messenger.class.getResourceAsStream("/config.json"), file.toPath(), StandardCopyOption.REPLACE_EXISTING);
31 | }
32 |
33 | final JsonObject jsonObject = new JsonParser().parse(new FileReader(file))
34 | .getAsJsonObject();
35 |
36 | final JsonObject poolObject = jsonObject.getAsJsonObject("pool");
37 | if (Objects.isNull(poolObject)) { // Added because of config update.
38 | Files.delete(file.toPath());
39 | Files.copy(Messenger.class.getResourceAsStream("/config.json"), file.toPath(), StandardCopyOption.REPLACE_EXISTING);
40 | }
41 |
42 | host = jsonObject.get("host").getAsString();
43 | port = jsonObject.get("port").getAsInt();
44 |
45 | pool = new Pool(poolObject.get("adjust-size-automatically").getAsBoolean(), poolObject.get("pool-size").getAsInt());
46 | }
47 |
48 | @Data
49 | public final class Pool {
50 |
51 | private final boolean adjustSizeAutomatically;
52 | private final int size;
53 |
54 | }
55 |
56 | }
--------------------------------------------------------------------------------
/messenger-plugin/src/main/java/me/hp888/messenger/velocity/VelocityMessengerPlugin.java:
--------------------------------------------------------------------------------
1 | package me.hp888.messenger.velocity;
2 |
3 | import com.google.inject.Inject;
4 | import com.velocitypowered.api.event.Subscribe;
5 | import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
6 | import com.velocitypowered.api.event.proxy.ProxyShutdownEvent;
7 | import com.velocitypowered.api.plugin.Plugin;
8 | import com.velocitypowered.api.plugin.annotation.DataDirectory;
9 | import com.velocitypowered.api.proxy.ProxyServer;
10 | import me.hp888.messenger.MessengerClient;
11 | import me.hp888.messenger.api.client.Client;
12 | import me.hp888.messenger.shared.Messenger;
13 | import me.hp888.messenger.shared.MessengerPlugin;
14 | import me.hp888.messenger.shared.config.Configuration;
15 | import java.io.File;
16 | import java.io.IOException;
17 | import java.net.InetSocketAddress;
18 | import java.nio.file.Path;
19 | import java.util.Objects;
20 | import java.util.logging.Level;
21 | import java.util.logging.Logger;
22 |
23 | /**
24 | * @author hp888 on 10.11.2020.
25 | */
26 |
27 | @Plugin(id = "messenger",
28 | name = "MessengerPlugin",
29 | authors = "HP888",
30 | version = "1.0"
31 | )
32 | public final class VelocityMessengerPlugin {
33 |
34 | private final Configuration configuration;
35 | private final ProxyServer server;
36 | private final Path dataFolder;
37 | private final Logger logger;
38 |
39 | @Inject
40 | public VelocityMessengerPlugin(ProxyServer server, Logger logger, @DataDirectory Path dataFolder) {
41 | this.server = server;
42 | this.logger = logger;
43 | this.dataFolder = dataFolder;
44 | this.configuration = new Configuration();
45 | }
46 |
47 | @Subscribe
48 | public void onProxyInitialization(ProxyInitializeEvent event) {
49 | try {
50 | configuration.load(new File(dataFolder.toFile(), "config.json"));
51 | } catch (IOException ex) {
52 | logger.log(Level.SEVERE, "Cannot load configuration!", ex);
53 | return;
54 | }
55 |
56 | final Configuration.Pool pool = configuration.getPool();
57 | final Client client;
58 |
59 | if (pool.isAdjustSizeAutomatically()) {
60 | client = new MessengerClient();
61 | } else {
62 | client = new MessengerClient(Math.max(2, pool.getSize()));
63 | }
64 |
65 | try {
66 | client.connect(new InetSocketAddress(configuration.getHost(), configuration.getPort()));
67 | } catch (IOException ex) {
68 | logger.log(Level.SEVERE, "Cannot connect to remote server!", ex);
69 | return;
70 | }
71 |
72 | Messenger.setInstance(new MessengerPlugin(client, logger));
73 | }
74 |
75 | @Subscribe
76 | public void onProxyShutdown(ProxyShutdownEvent event) {
77 | final MessengerPlugin messenger = Messenger.getInstance();
78 | if (Objects.isNull(messenger)) {
79 | return;
80 | }
81 |
82 | try {
83 | messenger.disconnect();
84 | } catch (IOException ignored) {}
85 | }
86 |
87 | }
--------------------------------------------------------------------------------
/messenger-plugin/src/main/resources/bungee.yml:
--------------------------------------------------------------------------------
1 | main: 'me.hp888.messenger.bungee.BungeeMessengerPlugin'
2 | version: '1.0'
3 | author: 'HP888'
4 | name: 'MessengerPlugin'
--------------------------------------------------------------------------------
/messenger-plugin/src/main/resources/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "host": "127.0.0.1",
3 | "port": 9999,
4 | "pool": {
5 | "adjust-size-automatically": true,
6 | "pool-size": 8
7 | }
8 | }
--------------------------------------------------------------------------------
/messenger-plugin/src/main/resources/plugin.yml:
--------------------------------------------------------------------------------
1 | main: 'me.hp888.messenger.bukkit.BukkitMessengerPlugin'
2 | version: '1.0'
3 | author: 'HP888'
4 | name: 'MessengerPlugin'
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | me.hp888
8 | messaging-system
9 | pom
10 | 1.1-SNAPSHOT
11 |
12 | messaging-server
13 | messaging-client
14 | messenger-plugin
15 |
16 |
17 |
18 |
19 | safemc-repository
20 | SafeMC Repository
21 | https://safemc.pl/repository/releases
22 |
23 |
24 |
25 |
26 |
27 | org.projectlombok
28 | lombok
29 | 1.18.12
30 | provided
31 |
32 |
33 |
34 |
35 | clean install
36 |
37 |
38 | org.apache.maven.plugins
39 | maven-shade-plugin
40 | 3.2.1
41 |
42 |
43 | package
44 |
45 | shade
46 |
47 |
48 |
49 |
50 | false
51 | ${project.name}-${project.version}
52 |
53 |
54 |
55 | org.apache.maven.plugins
56 | maven-compiler-plugin
57 | 3.8.0
58 |
59 | 1.8
60 | 1.8
61 |
62 |
63 |
64 |
65 |
66 |
--------------------------------------------------------------------------------