mirror of
https://github.com/Nan1t/NanoLimbo.git
synced 2026-02-09 10:26:14 +01:00
Some Netty optimizations
This commit is contained in:
@@ -182,23 +182,23 @@ public class ClientConnection extends ChannelInboundHandlerAdapter {
|
||||
return;
|
||||
}
|
||||
|
||||
sendPacket(PACKET_LOGIN_SUCCESS);
|
||||
writePacket(PACKET_LOGIN_SUCCESS);
|
||||
updateState(State.PLAY);
|
||||
|
||||
server.getConnections().addConnection(this);
|
||||
|
||||
sendPacket(PACKET_JOIN_GAME);
|
||||
sendPacket(PACKET_PLAYER_ABILITIES);
|
||||
sendPacket(PACKET_PLAYER_POS);
|
||||
sendPacket(PACKET_PLAYER_INFO);
|
||||
|
||||
sendKeepAlive();
|
||||
writePacket(PACKET_JOIN_GAME);
|
||||
writePacket(PACKET_PLAYER_ABILITIES);
|
||||
writePacket(PACKET_PLAYER_POS);
|
||||
writePacket(PACKET_PLAYER_INFO);
|
||||
|
||||
if (PACKET_BOSS_BAR != null)
|
||||
sendPacket(PACKET_BOSS_BAR);
|
||||
writePacket(PACKET_BOSS_BAR);
|
||||
|
||||
if (PACKET_JOIN_MESSAGE != null)
|
||||
sendPacket(PACKET_JOIN_MESSAGE);
|
||||
writePacket(PACKET_JOIN_MESSAGE);
|
||||
|
||||
sendKeepAlive();
|
||||
}
|
||||
|
||||
public void disconnectLogin(String reason){
|
||||
@@ -227,6 +227,14 @@ public class ClientConnection extends ChannelInboundHandlerAdapter {
|
||||
channel.writeAndFlush(packet).addListener(ChannelFutureListener.CLOSE);
|
||||
}
|
||||
|
||||
public void writePacket(Object packet){
|
||||
if (isConnected()) channel.write(packet, channel.voidPromise());
|
||||
}
|
||||
|
||||
public void flushPackets(){
|
||||
if (isConnected()) channel.flush();
|
||||
}
|
||||
|
||||
public boolean isConnected(){
|
||||
return channel.isActive();
|
||||
}
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
package ru.nanit.limbo.connection;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class GameProfile {
|
||||
|
||||
private UUID uuid;
|
||||
private String username;
|
||||
|
||||
public UUID getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public void setUuid(UUID uuid) {
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
}
|
||||
package ru.nanit.limbo.connection;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class GameProfile {
|
||||
|
||||
private UUID uuid;
|
||||
private String username;
|
||||
|
||||
public UUID getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public void setUuid(UUID uuid) {
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,32 @@
|
||||
package ru.nanit.limbo.protocol;
|
||||
|
||||
public class PreRenderedPacket implements PacketOut {
|
||||
|
||||
private final PacketOut packet;
|
||||
private byte[] message;
|
||||
|
||||
public PreRenderedPacket(PacketOut packet){
|
||||
this.packet = packet;
|
||||
}
|
||||
|
||||
public PacketOut getWrappedPacket(){
|
||||
return packet;
|
||||
}
|
||||
|
||||
public PreRenderedPacket render(){
|
||||
ByteMessage renderedMessage = ByteMessage.create();
|
||||
packet.encode(renderedMessage);
|
||||
this.message = renderedMessage.toByteArray();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void encode(ByteMessage msg) {
|
||||
msg.writeBytes(message);
|
||||
}
|
||||
|
||||
public static PreRenderedPacket of(PacketOut packet){
|
||||
return new PreRenderedPacket(packet).render();
|
||||
}
|
||||
}
|
||||
package ru.nanit.limbo.protocol;
|
||||
|
||||
public class PreRenderedPacket implements PacketOut {
|
||||
|
||||
private final PacketOut packet;
|
||||
private byte[] message;
|
||||
|
||||
public PreRenderedPacket(PacketOut packet){
|
||||
this.packet = packet;
|
||||
}
|
||||
|
||||
public PacketOut getWrappedPacket(){
|
||||
return packet;
|
||||
}
|
||||
|
||||
public PreRenderedPacket render(){
|
||||
ByteMessage renderedMessage = ByteMessage.create();
|
||||
packet.encode(renderedMessage);
|
||||
this.message = renderedMessage.toByteArray();
|
||||
renderedMessage.release();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void encode(ByteMessage msg) {
|
||||
msg.writeBytes(message);
|
||||
}
|
||||
|
||||
public static PreRenderedPacket of(PacketOut packet){
|
||||
return new PreRenderedPacket(packet).render();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
package ru.nanit.limbo.protocol.packets.play;
|
||||
|
||||
import ru.nanit.limbo.protocol.ByteMessage;
|
||||
import ru.nanit.limbo.protocol.PacketOut;
|
||||
|
||||
public class PacketPlayerAbilities implements PacketOut {
|
||||
|
||||
private int flags = 0x02;
|
||||
private float flyingSpeed = 0.0F;
|
||||
private float fieldOfView = 0.1F;
|
||||
|
||||
public void setFlags(int flags) {
|
||||
this.flags = flags;
|
||||
}
|
||||
|
||||
public void setFlyingSpeed(float flyingSpeed) {
|
||||
this.flyingSpeed = flyingSpeed;
|
||||
}
|
||||
|
||||
public void setFieldOfView(float fieldOfView) {
|
||||
this.fieldOfView = fieldOfView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void encode(ByteMessage msg) {
|
||||
msg.writeByte(flags);
|
||||
msg.writeFloat(flyingSpeed);
|
||||
msg.writeFloat(fieldOfView);
|
||||
}
|
||||
|
||||
}
|
||||
package ru.nanit.limbo.protocol.packets.play;
|
||||
|
||||
import ru.nanit.limbo.protocol.ByteMessage;
|
||||
import ru.nanit.limbo.protocol.PacketOut;
|
||||
|
||||
public class PacketPlayerAbilities implements PacketOut {
|
||||
|
||||
private int flags = 0x02;
|
||||
private float flyingSpeed = 0.0F;
|
||||
private float fieldOfView = 0.1F;
|
||||
|
||||
public void setFlags(int flags) {
|
||||
this.flags = flags;
|
||||
}
|
||||
|
||||
public void setFlyingSpeed(float flyingSpeed) {
|
||||
this.flyingSpeed = flyingSpeed;
|
||||
}
|
||||
|
||||
public void setFieldOfView(float fieldOfView) {
|
||||
this.fieldOfView = fieldOfView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void encode(ByteMessage msg) {
|
||||
msg.writeByte(flags);
|
||||
msg.writeFloat(flyingSpeed);
|
||||
msg.writeFloat(fieldOfView);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,8 +1,15 @@
|
||||
package ru.nanit.limbo.server;
|
||||
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.channel.ChannelOption;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.channel.ServerChannel;
|
||||
import io.netty.channel.epoll.Epoll;
|
||||
import io.netty.channel.epoll.EpollEventLoopGroup;
|
||||
import io.netty.channel.epoll.EpollServerSocketChannel;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||
import io.netty.util.ResourceLeakDetector;
|
||||
import napi.configurate.serializing.NodeSerializers;
|
||||
import ru.nanit.limbo.configuration.LimboConfig;
|
||||
import ru.nanit.limbo.configuration.SocketAddressSerializer;
|
||||
@@ -14,8 +21,7 @@ import ru.nanit.limbo.world.DimensionRegistry;
|
||||
|
||||
import java.net.SocketAddress;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public final class LimboServer {
|
||||
@@ -23,6 +29,10 @@ public final class LimboServer {
|
||||
private LimboConfig config;
|
||||
private Connections connections;
|
||||
private DimensionRegistry dimensionRegistry;
|
||||
private ScheduledFuture<?> keepAliveTask;
|
||||
|
||||
private EventLoopGroup bossGroup;
|
||||
private EventLoopGroup workerGroup;
|
||||
|
||||
public LimboConfig getConfig(){
|
||||
return config;
|
||||
@@ -39,6 +49,8 @@ public final class LimboServer {
|
||||
public void start() throws Exception {
|
||||
Logger.info("Starting server...");
|
||||
|
||||
ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.DISABLED);
|
||||
|
||||
NodeSerializers.register(SocketAddress.class, new SocketAddressSerializer());
|
||||
NodeSerializers.register(InfoForwarding.class, new InfoForwarding.Serializer());
|
||||
NodeSerializers.register(PingData.class, new PingData.Serializer());
|
||||
@@ -56,21 +68,55 @@ public final class LimboServer {
|
||||
|
||||
ClientConnection.preInitPackets(this);
|
||||
|
||||
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
|
||||
executor.scheduleAtFixedRate(this::broadcastKeepAlive, 0L, 5L, TimeUnit.SECONDS);
|
||||
startBootstrap();
|
||||
|
||||
new ServerBootstrap()
|
||||
.group(new NioEventLoopGroup(), new NioEventLoopGroup())
|
||||
.channel(NioServerSocketChannel.class)
|
||||
.childHandler(new ClientChannelInitializer(this))
|
||||
.localAddress(config.getAddress())
|
||||
.bind();
|
||||
keepAliveTask = workerGroup.scheduleAtFixedRate(this::broadcastKeepAlive, 0L, 5L, TimeUnit.SECONDS);
|
||||
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(this::stop, "NanoLimbo shutdown thread"));
|
||||
|
||||
Logger.info("Server started on %s", config.getAddress());
|
||||
}
|
||||
|
||||
private void startBootstrap(){
|
||||
Class<? extends ServerChannel> channelClass;
|
||||
|
||||
if (Epoll.isAvailable()){
|
||||
bossGroup = new EpollEventLoopGroup(1);
|
||||
workerGroup = new EpollEventLoopGroup(4);
|
||||
channelClass = EpollServerSocketChannel.class;
|
||||
Logger.debug("Using Epoll transport type");
|
||||
} else {
|
||||
bossGroup = new NioEventLoopGroup(1);
|
||||
workerGroup = new NioEventLoopGroup(4);
|
||||
channelClass = NioServerSocketChannel.class;
|
||||
Logger.debug("Using Java NIO transport type");
|
||||
}
|
||||
|
||||
new ServerBootstrap()
|
||||
.group(bossGroup, workerGroup)
|
||||
.channel(channelClass)
|
||||
.childHandler(new ClientChannelInitializer(this))
|
||||
.childOption(ChannelOption.TCP_NODELAY, true)
|
||||
.localAddress(config.getAddress())
|
||||
.bind();
|
||||
}
|
||||
|
||||
private void broadcastKeepAlive(){
|
||||
connections.getAllConnections().forEach(ClientConnection::sendKeepAlive);
|
||||
}
|
||||
|
||||
private void stop(){
|
||||
if (keepAliveTask != null){
|
||||
keepAliveTask.cancel(true);
|
||||
}
|
||||
|
||||
if (bossGroup != null){
|
||||
bossGroup.shutdownGracefully();
|
||||
}
|
||||
|
||||
if (workerGroup != null){
|
||||
workerGroup.shutdownGracefully();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ public final class Logger {
|
||||
}
|
||||
|
||||
public static void debug(Object msg, Object... args){
|
||||
print(Level.INFO, msg, null, args);
|
||||
print(Level.DEBUG, msg, null, args);
|
||||
}
|
||||
|
||||
public static void warning(Object msg, Object... args){
|
||||
|
||||
Reference in New Issue
Block a user