Mirror von
https://github.com/PaperMC/Velocity.git
synchronisiert 2024-11-16 21:10:30 +01:00
Start optimizing server list ping.
Dieser Commit ist enthalten in:
Ursprung
cb74210cd8
Commit
3bf252cf45
@ -7,10 +7,10 @@ fi
|
||||
|
||||
echo "Compiling libdeflate..."
|
||||
cd libdeflate || exit
|
||||
CFLAGS="-fPIC -O2" make
|
||||
CFLAGS="-fPIC -O2 -fomit-frame-pointer" make
|
||||
cd ..
|
||||
|
||||
CFLAGS="-O3 -I$JAVA_HOME/include/ -I$JAVA_HOME/include/linux/ -fPIC -shared -Wl,-z,noexecstack"
|
||||
CFLAGS="-O2 -I$JAVA_HOME/include/ -I$JAVA_HOME/include/linux/ -fPIC -shared -Wl,-z,noexecstack -fomit-frame-pointer"
|
||||
ARCH=$(uname -m)
|
||||
mkdir -p src/main/resources/linux_$ARCH
|
||||
gcc $CFLAGS -Ilibdeflate src/main/c/jni_util.c src/main/c/jni_zlib_deflate.c src/main/c/jni_zlib_inflate.c \
|
||||
|
@ -63,6 +63,23 @@ public class LibdeflateVelocityCompressor implements VelocityCompressor {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deflateSingle(ByteBuf source, ByteBuf destination) throws DataFormatException {
|
||||
ensureNotDisposed();
|
||||
|
||||
long sourceAddress = source.memoryAddress() + source.readerIndex();
|
||||
long destinationAddress = destination.memoryAddress() + destination.writerIndex();
|
||||
|
||||
int produced = deflate.process(deflateCtx, sourceAddress, source.readableBytes(),
|
||||
destinationAddress, destination.writableBytes());
|
||||
if (produced > 0) {
|
||||
destination.writerIndex(destination.writerIndex() + produced);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void ensureNotDisposed() {
|
||||
Preconditions.checkState(!disposed, "Object already disposed");
|
||||
}
|
||||
|
@ -14,4 +14,9 @@ public interface VelocityCompressor extends Disposable, Native {
|
||||
throws DataFormatException;
|
||||
|
||||
void deflate(ByteBuf source, ByteBuf destination) throws DataFormatException;
|
||||
|
||||
default boolean deflateSingle(ByteBuf source, ByteBuf destination) throws DataFormatException {
|
||||
deflate(source, destination);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ import com.velocitypowered.api.proxy.Player;
|
||||
import com.velocitypowered.api.proxy.ProxyServer;
|
||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||
import com.velocitypowered.api.proxy.server.ServerInfo;
|
||||
import com.velocitypowered.api.proxy.server.ServerPing;
|
||||
import com.velocitypowered.api.util.Favicon;
|
||||
import com.velocitypowered.api.util.GameProfile;
|
||||
import com.velocitypowered.api.util.ProxyVersion;
|
||||
@ -34,8 +35,11 @@ import com.velocitypowered.proxy.plugin.VelocityEventManager;
|
||||
import com.velocitypowered.proxy.plugin.VelocityPluginManager;
|
||||
import com.velocitypowered.proxy.protocol.ProtocolUtils;
|
||||
import com.velocitypowered.proxy.protocol.packet.Chat;
|
||||
import com.velocitypowered.proxy.protocol.util.FaviconSerializer;
|
||||
import com.velocitypowered.proxy.protocol.util.ping.FaviconSerializer;
|
||||
import com.velocitypowered.proxy.protocol.util.GameProfileSerializer;
|
||||
import com.velocitypowered.proxy.protocol.util.ping.PlayersSerializer;
|
||||
import com.velocitypowered.proxy.protocol.util.ping.ServerPingSerializer;
|
||||
import com.velocitypowered.proxy.protocol.util.ping.VersionSerializer;
|
||||
import com.velocitypowered.proxy.scheduler.VelocityScheduler;
|
||||
import com.velocitypowered.proxy.server.ServerMap;
|
||||
import com.velocitypowered.proxy.util.AddressUtil;
|
||||
@ -77,8 +81,6 @@ import java.util.stream.Collectors;
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.kyori.adventure.audience.ForwardingAudience;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import net.kyori.adventure.text.TranslatableComponent;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.asynchttpclient.AsyncHttpClient;
|
||||
@ -91,20 +93,26 @@ public class VelocityServer implements ProxyServer, ForwardingAudience {
|
||||
|
||||
private static final Logger logger = LogManager.getLogger(VelocityServer.class);
|
||||
public static final Gson GENERAL_GSON = new GsonBuilder()
|
||||
.registerTypeHierarchyAdapter(Favicon.class, FaviconSerializer.INSTANCE)
|
||||
.registerTypeAdapter(Favicon.class, FaviconSerializer.INSTANCE)
|
||||
.registerTypeHierarchyAdapter(GameProfile.class, GameProfileSerializer.INSTANCE)
|
||||
.create();
|
||||
private static final Gson PRE_1_16_PING_SERIALIZER = ProtocolUtils
|
||||
.getJsonChatSerializer(ProtocolVersion.MINECRAFT_1_15_2)
|
||||
.serializer()
|
||||
.newBuilder()
|
||||
.registerTypeHierarchyAdapter(Favicon.class, FaviconSerializer.INSTANCE)
|
||||
.registerTypeAdapter(Favicon.class, FaviconSerializer.INSTANCE)
|
||||
.registerTypeAdapter(ServerPing.class, ServerPingSerializer.INSTANCE)
|
||||
.registerTypeAdapter(ServerPing.Version.class, VersionSerializer.INSTANCE)
|
||||
.registerTypeAdapter(ServerPing.Players.class, PlayersSerializer.INSTANCE)
|
||||
.create();
|
||||
private static final Gson POST_1_16_PING_SERIALIZER = ProtocolUtils
|
||||
.getJsonChatSerializer(ProtocolVersion.MINECRAFT_1_16)
|
||||
.serializer()
|
||||
.newBuilder()
|
||||
.registerTypeHierarchyAdapter(Favicon.class, FaviconSerializer.INSTANCE)
|
||||
.registerTypeAdapter(Favicon.class, FaviconSerializer.INSTANCE)
|
||||
.registerTypeAdapter(ServerPing.class, ServerPingSerializer.INSTANCE)
|
||||
.registerTypeAdapter(ServerPing.Version.class, VersionSerializer.INSTANCE)
|
||||
.registerTypeAdapter(ServerPing.Players.class, PlayersSerializer.INSTANCE)
|
||||
.create();
|
||||
|
||||
private final ConnectionManager cm;
|
||||
|
@ -21,14 +21,20 @@ public class MinecraftCompressEncoder extends MessageToByteEncoder<ByteBuf> {
|
||||
protected void encode(ChannelHandlerContext ctx, ByteBuf msg, ByteBuf out) throws Exception {
|
||||
int uncompressed = msg.readableBytes();
|
||||
if (uncompressed <= threshold) {
|
||||
// Under the threshold, there is nothing to do.
|
||||
// Under the threshold, only indicate the message was too small
|
||||
ProtocolUtils.writeVarInt(out, 0);
|
||||
out.writeBytes(msg);
|
||||
} else {
|
||||
ProtocolUtils.writeVarInt(out, uncompressed);
|
||||
ByteBuf compatibleIn = MoreByteBufUtils.ensureCompatible(ctx.alloc(), compressor, msg);
|
||||
try {
|
||||
compressor.deflate(compatibleIn, out);
|
||||
if (!compressor.deflateSingle(compatibleIn, out)) {
|
||||
// The packet would have been too big. Clear the output buffer and use an uncompressed
|
||||
// packet instead.
|
||||
out.clear();
|
||||
ProtocolUtils.writeVarInt(out, 0);
|
||||
out.writeBytes(msg);
|
||||
}
|
||||
} finally {
|
||||
compatibleIn.release();
|
||||
}
|
||||
|
@ -1,29 +0,0 @@
|
||||
package com.velocitypowered.proxy.protocol.util;
|
||||
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import com.google.gson.JsonSerializationContext;
|
||||
import com.google.gson.JsonSerializer;
|
||||
import com.velocitypowered.api.util.Favicon;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
public final class FaviconSerializer implements JsonSerializer<Favicon>, JsonDeserializer<Favicon> {
|
||||
|
||||
public static final FaviconSerializer INSTANCE = new FaviconSerializer();
|
||||
|
||||
private FaviconSerializer() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Favicon deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) {
|
||||
return new Favicon(json.getAsString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonElement serialize(Favicon src, Type typeOfSrc, JsonSerializationContext context) {
|
||||
return new JsonPrimitive(src.getBase64Url());
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package com.velocitypowered.proxy.protocol.util.ping;
|
||||
|
||||
import com.google.gson.TypeAdapter;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
import com.velocitypowered.api.util.Favicon;
|
||||
import java.io.IOException;
|
||||
|
||||
public final class FaviconSerializer extends TypeAdapter<Favicon> {
|
||||
|
||||
public static final FaviconSerializer INSTANCE = new FaviconSerializer();
|
||||
|
||||
private FaviconSerializer() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(JsonWriter writer, Favicon favicon) throws IOException {
|
||||
writer.value(favicon.getBase64Url());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Favicon read(JsonReader reader) throws IOException {
|
||||
return new Favicon(reader.nextString());
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
package com.velocitypowered.proxy.protocol.util.ping;
|
||||
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.JsonSerializationContext;
|
||||
import com.google.gson.JsonSerializer;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.velocitypowered.api.proxy.server.ServerPing.Players;
|
||||
import com.velocitypowered.api.proxy.server.ServerPing.SamplePlayer;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.List;
|
||||
|
||||
public class PlayersSerializer implements JsonSerializer<Players>, JsonDeserializer<Players> {
|
||||
|
||||
public static final PlayersSerializer INSTANCE = new PlayersSerializer();
|
||||
|
||||
private PlayersSerializer() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Players deserialize(JsonElement elem, Type type,
|
||||
JsonDeserializationContext ctx) throws JsonParseException {
|
||||
JsonObject object = new JsonObject();
|
||||
int online = object.get("online").getAsInt();
|
||||
int max = object.get("max").getAsInt();
|
||||
List<SamplePlayer> sample = ctx.deserialize(object.get("sample"),
|
||||
new TypeToken<List<SamplePlayer>>() {}.getType());
|
||||
return new Players(online, max, sample);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonElement serialize(Players players, Type type, JsonSerializationContext ctx) {
|
||||
JsonObject object = new JsonObject();
|
||||
|
||||
object.addProperty("online", players.getOnline());
|
||||
object.addProperty("max", players.getMax());
|
||||
object.add("sample", ctx.serialize(players.getSample()));
|
||||
|
||||
return object;
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
package com.velocitypowered.proxy.protocol.util.ping;
|
||||
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.JsonSerializationContext;
|
||||
import com.google.gson.JsonSerializer;
|
||||
import com.velocitypowered.api.proxy.server.ServerPing;
|
||||
import com.velocitypowered.api.proxy.server.ServerPing.Players;
|
||||
import com.velocitypowered.api.proxy.server.ServerPing.Version;
|
||||
import com.velocitypowered.api.util.Favicon;
|
||||
import com.velocitypowered.api.util.ModInfo;
|
||||
import java.lang.reflect.Type;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
public class ServerPingSerializer implements JsonSerializer<ServerPing>,
|
||||
JsonDeserializer<ServerPing> {
|
||||
|
||||
public static final ServerPingSerializer INSTANCE = new ServerPingSerializer();
|
||||
|
||||
private ServerPingSerializer() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerPing deserialize(JsonElement elem, Type type,
|
||||
JsonDeserializationContext ctx) throws JsonParseException {
|
||||
JsonObject object = elem.getAsJsonObject();
|
||||
|
||||
Component description = ctx.deserialize(object.get("description"), Component.class);
|
||||
Version version = ctx.deserialize(object.get("version"), Version.class);
|
||||
Players players = ctx.deserialize(object.get("players"), Players.class);
|
||||
Favicon favicon = ctx.deserialize(object.get("favicon"), Favicon.class);
|
||||
ModInfo modInfo = ctx.deserialize(object.get("modInfo"), ModInfo.class);
|
||||
|
||||
return new ServerPing(version, players, description, favicon, modInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonElement serialize(ServerPing ping, Type type,
|
||||
JsonSerializationContext ctx) {
|
||||
JsonObject object = new JsonObject();
|
||||
object.add("description", ctx.serialize(ping.getDescriptionComponent()));
|
||||
object.add("version", ctx.serialize(ping.getVersion()));
|
||||
object.add("players", ctx.serialize(ping.getPlayers().orElse(null)));
|
||||
object.addProperty("favicon", ping.getFavicon().map(Favicon::getBase64Url).orElse(null));
|
||||
object.add("modInfo", ctx.serialize(ping.getModinfo().orElse(null)));
|
||||
return object;
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
package com.velocitypowered.proxy.protocol.util.ping;
|
||||
|
||||
import com.google.gson.TypeAdapter;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
import com.velocitypowered.api.proxy.server.ServerPing.Version;
|
||||
import java.io.IOException;
|
||||
|
||||
public class VersionSerializer extends TypeAdapter<Version> {
|
||||
|
||||
public static final VersionSerializer INSTANCE = new VersionSerializer();
|
||||
|
||||
private VersionSerializer() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(JsonWriter jsonWriter, Version version) throws IOException {
|
||||
jsonWriter.beginObject();
|
||||
jsonWriter.name("protocol");
|
||||
jsonWriter.value(version.getProtocol());
|
||||
jsonWriter.name("name");
|
||||
jsonWriter.value(version.getName());
|
||||
jsonWriter.endObject();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Version read(JsonReader jsonReader) throws IOException {
|
||||
jsonReader.beginObject();
|
||||
|
||||
String name = "";
|
||||
int protocol = -1;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
String elem = jsonReader.nextName();
|
||||
if (elem.equals("name")) {
|
||||
name = jsonReader.nextString();
|
||||
} else if (elem.equals("protocol")) {
|
||||
protocol = jsonReader.nextInt();
|
||||
} else {
|
||||
throw new IllegalStateException("Invalid version specification.");
|
||||
}
|
||||
}
|
||||
|
||||
jsonReader.endObject();
|
||||
return new Version(protocol, name);
|
||||
}
|
||||
}
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren