Return OptimisticNetworkManager
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
package io.akarin.server.mixin.nsc;
|
||||
|
||||
import java.util.Queue;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Overwrite;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
|
||||
import com.googlecode.concurentlocks.ReentrantReadWriteUpdateLock;
|
||||
|
||||
import io.akarin.api.internal.utils.CheckedConcurrentLinkedQueue;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.util.concurrent.Future;
|
||||
import io.netty.util.concurrent.GenericFutureListener;
|
||||
import net.minecraft.server.NetworkManager;
|
||||
import net.minecraft.server.NetworkManager.QueuedPacket;
|
||||
import net.minecraft.server.Packet;
|
||||
import net.minecraft.server.PacketPlayOutMapChunk;
|
||||
|
||||
@Mixin(value = NetworkManager.class, remap = false)
|
||||
public abstract class OptimisticNetworkManager {
|
||||
@Shadow public Channel channel;
|
||||
@Shadow(aliases = "i") @Final private Queue<NetworkManager.QueuedPacket> packets;
|
||||
@Shadow(aliases = "j") @Final private ReentrantReadWriteUpdateLock queueLock;
|
||||
|
||||
@Shadow public abstract Queue<NetworkManager.QueuedPacket> getPacketQueue();
|
||||
@Shadow public abstract void dispatchPacket(Packet<?> packet, GenericFutureListener<? extends Future<? super Void>>[] genericFutureListeners);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static final QueuedPacket SIGNAL_PACKET = new QueuedPacket(null);
|
||||
|
||||
@Overwrite // OBFHELPER: trySendQueue
|
||||
private boolean m() {
|
||||
if (this.channel != null && this.channel.isOpen()) {
|
||||
if (this.packets.isEmpty()) { // return if the packet queue is empty so that the write lock by Anti-Xray doesn't affect the vanilla performance at all
|
||||
return true;
|
||||
}
|
||||
|
||||
this.queueLock.updateLock().lock();
|
||||
try {
|
||||
while (!this.packets.isEmpty()) {
|
||||
NetworkManager.QueuedPacket packet = ((CheckedConcurrentLinkedQueue<QueuedPacket>) getPacketQueue()).poll(item -> {
|
||||
return item.getPacket() instanceof PacketPlayOutMapChunk && !((PacketPlayOutMapChunk) item.getPacket()).isReady();
|
||||
}, SIGNAL_PACKET);
|
||||
|
||||
if (packet != null) { // Fix NPE (Spigot bug caused by handleDisconnection())
|
||||
if (packet == SIGNAL_PACKET) {
|
||||
return false; // Return false if the peeked packet is a chunk packet which is not ready
|
||||
} else {
|
||||
dispatchPacket(packet.getPacket(), packet.getGenericFutureListeners()); // dispatch the packet
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
this.queueLock.updateLock().unlock();
|
||||
}
|
||||
|
||||
}
|
||||
return true; // Return true if all packets were dispatched
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user