chat sync reconnect system
This commit is contained in:
parent
05643bd0b4
commit
a5041917a4
|
|
@ -34,7 +34,7 @@ mod_name=PlayerSync
|
|||
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
|
||||
mod_license=GPL-3.0 license
|
||||
# The mod version. See https://semver.org/
|
||||
mod_version=2.1.3
|
||||
mod_version=2.1.4
|
||||
# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository.
|
||||
# This should match the base package used for the mod sources.
|
||||
# See https://maven.apache.org/guides/mini/guide-naming-conventions.html
|
||||
|
|
|
|||
|
|
@ -11,28 +11,45 @@ import java.io.IOException;
|
|||
|
||||
public class ChatSync {
|
||||
public static final Logger LOGGER = LogUtils.getLogger();
|
||||
private static ChatSyncServer chatSyncServer;
|
||||
private static ChatSyncClient chatSyncClient;
|
||||
|
||||
public static void register(){
|
||||
if(JdbcConfig.IS_CHAT_SERVER.get()) {
|
||||
LOGGER.info("Trying to setup chat server at port " + JdbcConfig.CHAT_SERVER_PORT.get());
|
||||
new Thread(()->{
|
||||
ChatSyncServer chatSyncServer = new ChatSyncServer();
|
||||
chatSyncServer = new ChatSyncServer();
|
||||
try {
|
||||
chatSyncServer.run();
|
||||
} catch (IOException e) {
|
||||
LOGGER.error("Unable to start chat server", e);
|
||||
}
|
||||
}).start();
|
||||
}, "ChatSync-Server").start();
|
||||
}
|
||||
|
||||
new Thread(()->{
|
||||
try {
|
||||
Thread.sleep(2000);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
|
||||
LOGGER.info("Trying to connect to chat server "
|
||||
+ JdbcConfig.CHAT_SERVER_IP.get()
|
||||
+ ":"
|
||||
+ JdbcConfig.CHAT_SERVER_PORT.get());
|
||||
ChatSyncClient chatSyncClient = new ChatSyncClient();
|
||||
chatSyncClient = new ChatSyncClient();
|
||||
chatSyncClient.run();
|
||||
}).start();
|
||||
}, "ChatSync-Client").start();
|
||||
MinecraftForge.EVENT_BUS.register(ChatSyncClient.class);
|
||||
}
|
||||
|
||||
public static void shutdown() {
|
||||
if (chatSyncServer != null) {
|
||||
chatSyncServer.shutdown();
|
||||
}
|
||||
if (chatSyncClient != null) {
|
||||
chatSyncClient.shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,13 +6,14 @@ import net.minecraftforge.event.entity.player.PlayerEvent;
|
|||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import vip.fubuki.playersync.PlayerSync;
|
||||
import vip.fubuki.playersync.config.JdbcConfig;
|
||||
import vip.fubuki.playersync.sync.ChatSync;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintWriter;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.util.Objects;
|
||||
|
||||
public class ChatSyncClient {
|
||||
|
|
@ -20,31 +21,97 @@ public class ChatSyncClient {
|
|||
static Socket clientSocket;
|
||||
static PrintWriter out;
|
||||
|
||||
private static volatile boolean running = true;
|
||||
private static final int RECONNECT_DELAY = 5000;
|
||||
private static final int MAX_RECONNECT_ATTEMPTS = 10;
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
clientSocket = new Socket(JdbcConfig.CHAT_SERVER_IP.get(), JdbcConfig.CHAT_SERVER_PORT.get());
|
||||
out = new PrintWriter(clientSocket.getOutputStream(),true);
|
||||
int reconnectAttempts = 0;
|
||||
|
||||
BufferedReader in = new BufferedReader(
|
||||
new InputStreamReader(clientSocket.getInputStream()));
|
||||
while (running && reconnectAttempts < MAX_RECONNECT_ATTEMPTS) {
|
||||
try {
|
||||
PlayerSync.LOGGER.info("Connecting to chat server {}:{}",
|
||||
JdbcConfig.CHAT_SERVER_IP.get(),
|
||||
JdbcConfig.CHAT_SERVER_PORT.get());
|
||||
|
||||
String serverMessage;
|
||||
while ((serverMessage = in.readLine()) != null) {
|
||||
PlayerSync.LOGGER.info("Received message from chat server: " + serverMessage);
|
||||
Component textComponents = Component.nullToEmpty(serverMessage);
|
||||
if(playerList != null){
|
||||
playerList.broadcastSystemMessage(textComponents,false);
|
||||
clientSocket = new Socket();
|
||||
|
||||
clientSocket.connect(
|
||||
new InetSocketAddress(
|
||||
JdbcConfig.CHAT_SERVER_IP.get(),
|
||||
JdbcConfig.CHAT_SERVER_PORT.get()
|
||||
),
|
||||
10000
|
||||
);
|
||||
|
||||
clientSocket.setSoTimeout(30000);
|
||||
|
||||
out = new PrintWriter(clientSocket.getOutputStream(), true);
|
||||
BufferedReader in = new BufferedReader(
|
||||
new InputStreamReader(clientSocket.getInputStream()));
|
||||
|
||||
PlayerSync.LOGGER.info("Successfully connected to chat server");
|
||||
reconnectAttempts = 0;
|
||||
|
||||
String serverMessage;
|
||||
while (running && (serverMessage = in.readLine()) != null) {
|
||||
PlayerSync.LOGGER.info("Received message from chat server: " + serverMessage);
|
||||
Component textComponents = Component.nullToEmpty(serverMessage);
|
||||
if(playerList != null){
|
||||
if (playerList.getServer().isSameThread()) {
|
||||
playerList.broadcastSystemMessage(textComponents, false);
|
||||
} else {
|
||||
playerList.getServer().execute(() ->
|
||||
playerList.broadcastSystemMessage(textComponents, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (SocketTimeoutException e) {
|
||||
PlayerSync.LOGGER.warn("Chat server connection timeout, reconnecting...");
|
||||
} catch (IOException e) {
|
||||
PlayerSync.LOGGER.error("Chat client connection error: {}", e.getMessage());
|
||||
} finally {
|
||||
closeConnection();
|
||||
}
|
||||
|
||||
if (running && reconnectAttempts < MAX_RECONNECT_ATTEMPTS) {
|
||||
reconnectAttempts++;
|
||||
PlayerSync.LOGGER.warn("Attempting to reconnect to chat server ({}/{})",
|
||||
reconnectAttempts, MAX_RECONNECT_ATTEMPTS);
|
||||
|
||||
try {
|
||||
Thread.sleep(RECONNECT_DELAY);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
reconnectClient();
|
||||
}
|
||||
|
||||
if (reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {
|
||||
PlayerSync.LOGGER.error("Failed to connect to chat server after {} attempts", MAX_RECONNECT_ATTEMPTS);
|
||||
}
|
||||
}
|
||||
|
||||
private void reconnectClient() {
|
||||
ChatSync.LOGGER.warn("TODO: implement reconnectClient()");
|
||||
//TODO
|
||||
private void closeConnection() {
|
||||
try {
|
||||
if (out != null) {
|
||||
out.close();
|
||||
out = null;
|
||||
}
|
||||
if (clientSocket != null && !clientSocket.isClosed()) {
|
||||
clientSocket.close();
|
||||
clientSocket = null;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
PlayerSync.LOGGER.error("Error closing connection: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
running = false;
|
||||
closeConnection();
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
|
|
|
|||
|
|
@ -1,63 +1,131 @@
|
|||
package vip.fubuki.playersync.sync.chat;
|
||||
|
||||
import vip.fubuki.playersync.PlayerSync;
|
||||
import vip.fubuki.playersync.config.JdbcConfig;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintWriter;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class ChatSyncServer {
|
||||
static ServerSocket serverSocket;
|
||||
static final Set<Socket> SocketList = ConcurrentHashMap.newKeySet();
|
||||
static final ExecutorService executorService = Executors.newCachedThreadPool();
|
||||
private volatile boolean running = true;
|
||||
|
||||
public void run() throws IOException {
|
||||
serverSocket = new ServerSocket(JdbcConfig.CHAT_SERVER_PORT.get());
|
||||
while (!Thread.currentThread().isInterrupted()) {
|
||||
Socket newSocket = serverSocket.accept();
|
||||
SocketList.add(newSocket);
|
||||
executorService.submit(() -> handleClient(newSocket));
|
||||
try {
|
||||
serverSocket = new ServerSocket(JdbcConfig.CHAT_SERVER_PORT.get());
|
||||
serverSocket.setReuseAddress(true);
|
||||
PlayerSync.LOGGER.info("Chat server started successfully on port {}", JdbcConfig.CHAT_SERVER_PORT.get());
|
||||
|
||||
while (running && !Thread.currentThread().isInterrupted()) {
|
||||
try {
|
||||
Socket newSocket = serverSocket.accept();
|
||||
newSocket.setSoTimeout(30000);
|
||||
SocketList.add(newSocket);
|
||||
executorService.submit(() -> handleClient(newSocket));
|
||||
PlayerSync.LOGGER.info("New client connected, total clients: {}", SocketList.size());
|
||||
} catch (IOException e) {
|
||||
if (running) {
|
||||
PlayerSync.LOGGER.error("Error accepting client connection: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
shutdown();
|
||||
}
|
||||
serverSocket.close();
|
||||
}
|
||||
|
||||
private void handleClient(Socket socket) {
|
||||
try (InputStream inputStream = socket.getInputStream()) {
|
||||
byte[] buffer = new byte[1024];
|
||||
int bytesRead;
|
||||
while ((bytesRead = inputStream.read(buffer)) != -1) {
|
||||
String message = new String(buffer, 0, bytesRead);
|
||||
String clientInfo = socket.getInetAddress() + ":" + socket.getPort();
|
||||
|
||||
try (BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(socket.getInputStream()))) {
|
||||
|
||||
String message;
|
||||
while (running && (message = reader.readLine()) != null) {
|
||||
PlayerSync.LOGGER.info("Received message from {}: {}", clientInfo, message);
|
||||
broadcastMessage(socket, message);
|
||||
}
|
||||
|
||||
} catch (SocketTimeoutException e) {
|
||||
PlayerSync.LOGGER.warn("Client {} timeout", clientInfo);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
PlayerSync.LOGGER.error("Error handling client {}: {}", clientInfo, e.getMessage());
|
||||
} finally {
|
||||
SocketList.remove(socket);
|
||||
try {
|
||||
socket.close();
|
||||
if (!socket.isClosed()) {
|
||||
socket.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
PlayerSync.LOGGER.error("Error closing client socket: {}", e.getMessage());
|
||||
}
|
||||
PlayerSync.LOGGER.info("Client disconnected, remaining clients: {}", SocketList.size());
|
||||
}
|
||||
}
|
||||
|
||||
private void broadcastMessage(Socket sender, String message) {
|
||||
for (Socket socket : SocketList) {
|
||||
if (!socket.equals(sender)) {
|
||||
Iterator<Socket> iterator = SocketList.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Socket socket = iterator.next();
|
||||
if (!socket.equals(sender) && !socket.isClosed()) {
|
||||
try {
|
||||
OutputStream outputStream = socket.getOutputStream();
|
||||
outputStream.write(message.getBytes());
|
||||
outputStream.flush();
|
||||
PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
|
||||
writer.println(message);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
PlayerSync.LOGGER.error("Error broadcasting to client, removing: {}", e.getMessage());
|
||||
iterator.remove();
|
||||
try {
|
||||
socket.close();
|
||||
} catch (IOException ex) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
running = false;
|
||||
try {
|
||||
if (serverSocket != null && !serverSocket.isClosed()) {
|
||||
serverSocket.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
PlayerSync.LOGGER.error("Error closing server socket: {}", e.getMessage());
|
||||
}
|
||||
|
||||
for (Socket socket : SocketList) {
|
||||
try {
|
||||
if (!socket.isClosed()) {
|
||||
socket.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
SocketList.clear();
|
||||
|
||||
executorService.shutdown();
|
||||
try {
|
||||
if (!executorService.awaitTermination(5, TimeUnit.SECONDS)) {
|
||||
executorService.shutdownNow();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
executorService.shutdownNow();
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user