Keeping use mixin

This commit is contained in:
Sotr
2018-06-09 03:08:06 +08:00
parent 3b30c6b5f3
commit 02d56f9ed6
5 changed files with 78 additions and 8 deletions

View File

@@ -0,0 +1,14 @@
package io.akarin.server.mixin.core;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import net.minecraft.server.PlayerConnection;
@Mixin(value = PlayerConnection.class, remap = false)
public class MixinPlayerConnection {
@Overwrite
private long d() {
return System.currentTimeMillis();
}
}

View File

@@ -0,0 +1,55 @@
package io.akarin.server.mixin.core;
import java.util.Queue;
import java.util.concurrent.locks.ReentrantReadWriteLock;
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 io.akarin.api.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.Packet;
@Mixin(value = NetworkManager.class, remap = false)
public class OptimisticNetworkManager {
@Shadow public Channel channel;
@Shadow @Final private Queue<NetworkManager.QueuedPacket> i;
@Shadow @Final private ReentrantReadWriteLock j;
@Shadow private Queue<NetworkManager.QueuedPacket> getPacketQueue() { return null; }
@Shadow private void dispatchPacket(Packet<?> packet, GenericFutureListener<? extends Future<? super Void>>[] genericFutureListeners) {}
@Overwrite
private boolean m() {
if (this.channel != null && this.channel.isOpen()) {
if (this.i.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.j.readLock().lock();
try {
while (!this.i.isEmpty()) {
NetworkManager.QueuedPacket packet = ((CheckedConcurrentLinkedQueue) getPacketQueue()).checkedPoll();
if (packet != null) { // Fix NPE (Spigot bug caused by handleDisconnection())
if (packet == CheckedConcurrentLinkedQueue.emptyPacket) { // Check if the peeked packet is a chunk packet which is not ready
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.j.readLock().unlock();
}
}
return true; // Return true if all packets were dispatched
}
}

View File

@@ -240,23 +240,23 @@ public class NetworkManager extends SimpleChannelInboundHandler<Packet<?>> {
return true; return true;
} }
this.j.readLock().lock(); // readLock -> writeLock (because of race condition between peek and poll) // Akarin - writeLock -> readLock this.j.writeLock().lock(); // readLock -> writeLock (because of race condition between peek and poll)
try { try {
while (!this.i.isEmpty()) { while (!this.i.isEmpty()) {
NetworkManager.QueuedPacket networkmanager_queuedpacket = ((CheckedConcurrentLinkedQueue) this.getPacketQueue()).checkedPoll(); // poll -> peek // Akarin NetworkManager.QueuedPacket networkmanager_queuedpacket = this.getPacketQueue().peek(); // poll -> peek
if (networkmanager_queuedpacket != null) { // Fix NPE (Spigot bug caused by handleDisconnection()) if (networkmanager_queuedpacket != null) { // Fix NPE (Spigot bug caused by handleDisconnection())
if (networkmanager_queuedpacket == CheckedConcurrentLinkedQueue.emptyPacket) { // Check if the peeked packet is a chunk packet which is not ready // Akarin if (networkmanager_queuedpacket.getPacket() instanceof PacketPlayOutMapChunk && !((PacketPlayOutMapChunk) networkmanager_queuedpacket.getPacket()).isReady()) { // Check if the peeked packet is a chunk packet which is not ready
return false; // Return false if the peeked packet is a chunk packet which is not ready return false; // Return false if the peeked packet is a chunk packet which is not ready
} else { } else {
// this.getPacketQueue().poll(); // poll here // Akarin - polled this.getPacketQueue().poll(); // poll here
this.dispatchPacket(networkmanager_queuedpacket.getPacket(), networkmanager_queuedpacket.getGenericFutureListeners()); // dispatch the packet this.dispatchPacket(networkmanager_queuedpacket.getPacket(), networkmanager_queuedpacket.getGenericFutureListeners()); // dispatch the packet
} }
} }
} }
} finally { } finally {
this.j.readLock().unlock(); // readLock -> writeLock (because of race condition between peek and poll) // Akarin - writeLock -> readLock this.j.writeLock().unlock(); // readLock -> writeLock (because of race condition between peek and poll)
} }
} }
@@ -372,7 +372,7 @@ public class NetworkManager extends SimpleChannelInboundHandler<Packet<?>> {
public static class QueuedPacket { // Akarin - default -> public public static class QueuedPacket { // Akarin - default -> public
private final Packet<?> a; public final Packet<?> getPacket() { return this.a; } // Paper - Anti-Xray - OBFHELPER // Akarin - private -> public private final Packet<?> a; public final Packet<?> getPacket() { return this.a; } // Paper - Anti-Xray - OBFHELPER // Akarin - private -> public
private final GenericFutureListener<? extends Future<? super Void>>[] b; private final GenericFutureListener<? extends Future<? super Void>>[] getGenericFutureListeners() { return this.b; } // Paper - Anti-Xray - OBFHELPER private final GenericFutureListener<? extends Future<? super Void>>[] b; public final GenericFutureListener<? extends Future<? super Void>>[] getGenericFutureListeners() { return this.b; } // Paper - Anti-Xray - OBFHELPER // Akarin - private -> public
public QueuedPacket(Packet<?> packet, GenericFutureListener<? extends Future<? super Void>>... agenericfuturelistener) { public QueuedPacket(Packet<?> packet, GenericFutureListener<? extends Future<? super Void>>... agenericfuturelistener) {
this.a = packet; this.a = packet;

View File

@@ -66,7 +66,6 @@ import co.aikar.timings.MinecraftTimings; // Paper
* 1) Add volatile to fields<br> * 1) Add volatile to fields<br>
* 2) Expose private members<br> * 2) Expose private members<br>
* 3) Migrated keep alive packet handling to service thread<br> * 3) Migrated keep alive packet handling to service thread<br>
* 4) Use currentMillis() instead of nanoTime() / 1000000
* @author cakoyo * @author cakoyo
*/ */
public class PlayerConnection implements PacketListenerPlayIn, ITickable { public class PlayerConnection implements PacketListenerPlayIn, ITickable {
@@ -2299,7 +2298,7 @@ public class PlayerConnection implements PacketListenerPlayIn, ITickable {
private long getCurrentMillis() { return d(); } // Paper - OBFHELPER private long getCurrentMillis() { return d(); } // Paper - OBFHELPER
private long d() { private long d() {
return System.currentTimeMillis(); // Akarin return System.nanoTime() / 1000000L;
} }
@Override @Override

View File

@@ -11,6 +11,7 @@
"DesyncCatcher", "DesyncCatcher",
"ParallelRegistry", "ParallelRegistry",
"MetricsBootstrap", "MetricsBootstrap",
"OptimisticNetworkManager",
"NonblockingServerConnection", "NonblockingServerConnection",
"MixinMCUtil", "MixinMCUtil",
@@ -19,6 +20,7 @@
"MixinVersionCommand", "MixinVersionCommand",
"MixinMinecraftServer", "MixinMinecraftServer",
"MixinChunkIOExecutor", "MixinChunkIOExecutor",
"MixinPlayerConnection",
"MixinTileEntityEnchantTable" "MixinTileEntityEnchantTable"
] ]
} }