Server/Server/src/main/core/net/IoEventHandler.java
Ceikry ff18f69dd0 Fixed a bug that was causing players to get stuck logged in
Fixed a bug that would cause players to get stuck in a client crash loop when logging out inside of a POH
Fixed a bug that let players reach objects that shouldn't be reachable
General disconnection reliability improvements
Adjusted the color of global chat for HD mode, the new color is #f1b04c
2023-03-05 11:00:06 +00:00

114 lines
No EOL
3 KiB
Java

package core.net;
import core.game.world.repository.Repository;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.concurrent.ExecutorService;
/**
* I/O event handling.
* @author Emperor
*/
public class IoEventHandler {
/**
* The executor service.
*/
protected final ExecutorService service;
/**
* Constructs a new {@code IoEventHandler}.
* @param service The executor service used for handling events.
*/
public IoEventHandler(ExecutorService service) {
this.service = service;
}
/**
* Called when making a new connection.
* @param key The selection key.
* @throws IOException When an I/O exception occurs.
*/
public void connect(SelectionKey key) throws IOException {
/*
* empty.
*/
}
/**
* Used for accepting a new connection.
* @param key The selection key.
* @param selector The selector.
* @throws IOException When an I/O exception occurs.
*/
public void accept(SelectionKey key, Selector selector) throws IOException {
SocketChannel sc = ((ServerSocketChannel) key.channel()).accept();
sc.configureBlocking(false);
sc.socket().setTcpNoDelay(true);
sc.register(selector, SelectionKey.OP_READ);
}
/**
* Reads the incoming packet data.
* @param key The selection key.
* @throws IOException When an I/O exception occurs.
*/
public void read(SelectionKey key) throws IOException {
ReadableByteChannel channel = (ReadableByteChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(100_000);
IoSession session = (IoSession) key.attachment();
try {
if (channel.read(buffer) == -1) {
if (session != null) {
session.disconnect();
}
key.cancel();
return;
}
} catch (IOException e) {
if (e.getMessage().contains("reset by peer") && session != null) {
session.disconnect();
} else {
key.cancel();
return;
}
}
buffer.flip();
if (session == null) {
key.attach(session = new IoSession(key, service));
}
service.execute(session.getProducer().produceReader(session, buffer));
}
/**
* Writes the outgoing packet data.
* @param key The selection key.
*/
public void write(SelectionKey key) {
IoSession session = (IoSession) key.attachment();
key.interestOps(key.interestOps() & ~SelectionKey.OP_WRITE);
session.write();
}
/**
* Disconnects a connection.
* @param key The selection key.
* @param t The occurred exception (if any).
*/
public void disconnect(SelectionKey key, Throwable t) {
try {
IoSession session = (IoSession) key.attachment();
String cause = "" + t;
if (t != null && !(t instanceof ClosedChannelException || cause.contains("De externe host") || cause.contains("De software op uw") || cause.contains("An established connection was aborted") || cause.contains("An existing connection") || cause.contains("AsynchronousClose"))) {
t.printStackTrace();
}
if (session != null) {
session.disconnect();
}
} catch (Throwable e) {
e.printStackTrace();
}
}
}