Mirror von
https://github.com/PaperMC/Velocity.git
synchronisiert 2024-11-17 05:20:14 +01:00
Merge branch 'dev/1.1.0' into experiment/io_uring
Dieser Commit ist enthalten in:
Commit
a9c4f04c02
@ -28,9 +28,7 @@ sure that you are properly adhering to the code style.
|
|||||||
To reduce bugs and ensure code quality, we run the following tools on all commits
|
To reduce bugs and ensure code quality, we run the following tools on all commits
|
||||||
and pull requests:
|
and pull requests:
|
||||||
|
|
||||||
* [Checker Framework](https://checkerframework.org/): an enhancement to Java's type
|
* [SpotBugs](https://spotbugs.github.io/): ensures that common errors do not
|
||||||
system that is designed to help catch bugs. Velocity runs the _Nullness Checker_
|
get into the codebase. The build will fail if SpotBugs finds an issue.
|
||||||
and the _Optional Checker_. The build will fail if Checker Framework notices an
|
|
||||||
issue.
|
|
||||||
* [Checkstyle](http://checkstyle.sourceforge.net/): ensures that your code is
|
* [Checkstyle](http://checkstyle.sourceforge.net/): ensures that your code is
|
||||||
correctly formatted. The build will fail if Checkstyle detects a problem.
|
correctly formatted. The build will fail if Checkstyle detects a problem.
|
@ -21,7 +21,7 @@ allprojects {
|
|||||||
ext {
|
ext {
|
||||||
// dependency versions
|
// dependency versions
|
||||||
textVersion = '3.0.4'
|
textVersion = '3.0.4'
|
||||||
adventureVersion = '4.3.0'
|
adventureVersion = '4.4.0'
|
||||||
adventurePlatformVersion = '4.0.0-SNAPSHOT'
|
adventurePlatformVersion = '4.0.0-SNAPSHOT'
|
||||||
junitVersion = '5.7.0'
|
junitVersion = '5.7.0'
|
||||||
slf4jVersion = '1.7.30'
|
slf4jVersion = '1.7.30'
|
||||||
|
@ -58,6 +58,7 @@ dependencies {
|
|||||||
implementation "org.apache.logging.log4j:log4j-core:${log4jVersion}"
|
implementation "org.apache.logging.log4j:log4j-core:${log4jVersion}"
|
||||||
implementation "org.apache.logging.log4j:log4j-slf4j-impl:${log4jVersion}"
|
implementation "org.apache.logging.log4j:log4j-slf4j-impl:${log4jVersion}"
|
||||||
implementation "org.apache.logging.log4j:log4j-iostreams:${log4jVersion}"
|
implementation "org.apache.logging.log4j:log4j-iostreams:${log4jVersion}"
|
||||||
|
implementation "org.apache.logging.log4j:log4j-jul:${log4jVersion}"
|
||||||
|
|
||||||
implementation 'net.sf.jopt-simple:jopt-simple:5.0.4' // command-line options
|
implementation 'net.sf.jopt-simple:jopt-simple:5.0.4' // command-line options
|
||||||
implementation 'net.minecrell:terminalconsoleappender:1.2.0'
|
implementation 'net.minecrell:terminalconsoleappender:1.2.0'
|
||||||
|
@ -8,9 +8,12 @@ import org.apache.logging.log4j.Logger;
|
|||||||
|
|
||||||
public class Velocity {
|
public class Velocity {
|
||||||
|
|
||||||
private static final Logger logger = LogManager.getLogger(Velocity.class);
|
private static final Logger logger;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
System.setProperty("java.util.logging.manager", "org.apache.logging.log4j.jul.LogManager");
|
||||||
|
logger = LogManager.getLogger(Velocity.class);
|
||||||
|
|
||||||
// We use BufferedImage for favicons, and on macOS this puts the Java application in the dock.
|
// We use BufferedImage for favicons, and on macOS this puts the Java application in the dock.
|
||||||
// How inconvenient. Force AWT to work with its head chopped off.
|
// How inconvenient. Force AWT to work with its head chopped off.
|
||||||
System.setProperty("java.awt.headless", "true");
|
System.setProperty("java.awt.headless", "true");
|
||||||
|
@ -38,6 +38,7 @@ import net.kyori.adventure.text.TextComponent;
|
|||||||
import net.kyori.adventure.text.event.ClickEvent;
|
import net.kyori.adventure.text.event.ClickEvent;
|
||||||
import net.kyori.adventure.text.event.HoverEvent;
|
import net.kyori.adventure.text.event.HoverEvent;
|
||||||
import net.kyori.adventure.text.format.NamedTextColor;
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
import net.kyori.adventure.text.format.TextColor;
|
||||||
import net.kyori.adventure.text.format.TextDecoration;
|
import net.kyori.adventure.text.format.TextDecoration;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
@ -188,6 +189,7 @@ public class VelocityCommand implements SimpleCommand {
|
|||||||
|
|
||||||
private static class Info implements SubCommand {
|
private static class Info implements SubCommand {
|
||||||
|
|
||||||
|
private static final TextColor VELOCITY_COLOR = TextColor.fromHexString("#09add3");
|
||||||
private final ProxyServer server;
|
private final ProxyServer server;
|
||||||
|
|
||||||
private Info(ProxyServer server) {
|
private Info(ProxyServer server) {
|
||||||
@ -205,7 +207,7 @@ public class VelocityCommand implements SimpleCommand {
|
|||||||
|
|
||||||
TextComponent velocity = Component.text().content(version.getName() + " ")
|
TextComponent velocity = Component.text().content(version.getName() + " ")
|
||||||
.decoration(TextDecoration.BOLD, true)
|
.decoration(TextDecoration.BOLD, true)
|
||||||
.color(NamedTextColor.DARK_AQUA)
|
.color(VELOCITY_COLOR)
|
||||||
.append(Component.text(version.getVersion()).decoration(TextDecoration.BOLD, false))
|
.append(Component.text(version.getVersion()).decoration(TextDecoration.BOLD, false))
|
||||||
.build();
|
.build();
|
||||||
TextComponent copyright = Component
|
TextComponent copyright = Component
|
||||||
|
@ -458,7 +458,7 @@ public class VelocityConfiguration implements ProxyConfig {
|
|||||||
PingPassthroughMode.DISABLED);
|
PingPassthroughMode.DISABLED);
|
||||||
|
|
||||||
String bind = config.getOrElse("bind", "0.0.0.0:25577");
|
String bind = config.getOrElse("bind", "0.0.0.0:25577");
|
||||||
String motd = config.getOrElse("motd", "&3A Velocity Server");
|
String motd = config.getOrElse("motd", "	add3A Velocity Server");
|
||||||
int maxPlayers = config.getIntOrElse("show-max-players", 500);
|
int maxPlayers = config.getIntOrElse("show-max-players", 500);
|
||||||
Boolean onlineMode = config.getOrElse("online-mode", true);
|
Boolean onlineMode = config.getOrElse("online-mode", true);
|
||||||
Boolean announceForge = config.getOrElse("announce-forge", true);
|
Boolean announceForge = config.getOrElse("announce-forge", true);
|
||||||
|
@ -83,7 +83,7 @@ public class BackendPlaySessionHandler implements MinecraftSessionHandler {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean handle(KeepAlive packet) {
|
public boolean handle(KeepAlive packet) {
|
||||||
serverConn.setLastPingId(packet.getRandomId());
|
serverConn.getPendingPings().put(packet.getRandomId(), System.currentTimeMillis());
|
||||||
return false; // forwards on
|
return false; // forwards on
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +29,9 @@ import io.netty.buffer.Unpooled;
|
|||||||
import io.netty.channel.ChannelFutureListener;
|
import io.netty.channel.ChannelFutureListener;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.function.UnaryOperator;
|
import java.util.function.UnaryOperator;
|
||||||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||||
@ -44,8 +46,7 @@ public class VelocityServerConnection implements MinecraftConnectionAssociation,
|
|||||||
private boolean hasCompletedJoin = false;
|
private boolean hasCompletedJoin = false;
|
||||||
private boolean gracefulDisconnect = false;
|
private boolean gracefulDisconnect = false;
|
||||||
private BackendConnectionPhase connectionPhase = BackendConnectionPhases.UNKNOWN;
|
private BackendConnectionPhase connectionPhase = BackendConnectionPhases.UNKNOWN;
|
||||||
private long lastPingId;
|
private final Map<Long, Long> pendingPings = new HashMap<>();
|
||||||
private long lastPingSent;
|
|
||||||
private @MonotonicNonNull DimensionRegistry activeDimensionRegistry;
|
private @MonotonicNonNull DimensionRegistry activeDimensionRegistry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -244,21 +245,8 @@ public class VelocityServerConnection implements MinecraftConnectionAssociation,
|
|||||||
return gracefulDisconnect;
|
return gracefulDisconnect;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getLastPingId() {
|
public Map<Long, Long> getPendingPings() {
|
||||||
return lastPingId;
|
return pendingPings;
|
||||||
}
|
|
||||||
|
|
||||||
public long getLastPingSent() {
|
|
||||||
return lastPingSent;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setLastPingId(long lastPingId) {
|
|
||||||
this.lastPingId = lastPingId;
|
|
||||||
this.lastPingSent = System.currentTimeMillis();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void resetLastPingId() {
|
|
||||||
this.lastPingId = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -99,12 +99,14 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
|
|||||||
@Override
|
@Override
|
||||||
public boolean handle(KeepAlive packet) {
|
public boolean handle(KeepAlive packet) {
|
||||||
VelocityServerConnection serverConnection = player.getConnectedServer();
|
VelocityServerConnection serverConnection = player.getConnectedServer();
|
||||||
if (serverConnection != null && packet.getRandomId() == serverConnection.getLastPingId()) {
|
if (serverConnection != null) {
|
||||||
MinecraftConnection smc = serverConnection.getConnection();
|
Long sentTime = serverConnection.getPendingPings().remove(packet.getRandomId());
|
||||||
if (smc != null) {
|
if (sentTime != null) {
|
||||||
player.setPing(System.currentTimeMillis() - serverConnection.getLastPingSent());
|
MinecraftConnection smc = serverConnection.getConnection();
|
||||||
smc.write(packet);
|
if (smc != null) {
|
||||||
serverConnection.resetLastPingId();
|
player.setPing(System.currentTimeMillis() - sentTime);
|
||||||
|
smc.write(packet);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -36,6 +36,7 @@ import io.netty.buffer.ByteBuf;
|
|||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.security.GeneralSecurityException;
|
import java.security.GeneralSecurityException;
|
||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
|
import java.security.MessageDigest;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
@ -90,7 +91,7 @@ public class LoginSessionHandler implements MinecraftSessionHandler {
|
|||||||
try {
|
try {
|
||||||
KeyPair serverKeyPair = server.getServerKeyPair();
|
KeyPair serverKeyPair = server.getServerKeyPair();
|
||||||
byte[] decryptedVerifyToken = decryptRsa(serverKeyPair, packet.getVerifyToken());
|
byte[] decryptedVerifyToken = decryptRsa(serverKeyPair, packet.getVerifyToken());
|
||||||
if (!Arrays.equals(verify, decryptedVerifyToken)) {
|
if (!MessageDigest.isEqual(verify, decryptedVerifyToken)) {
|
||||||
throw new IllegalStateException("Unable to successfully decrypt the verification token.");
|
throw new IllegalStateException("Unable to successfully decrypt the verification token.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,4 +11,12 @@ public interface MinecraftPacket {
|
|||||||
void encode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion);
|
void encode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion protocolVersion);
|
||||||
|
|
||||||
boolean handle(MinecraftSessionHandler handler);
|
boolean handle(MinecraftSessionHandler handler);
|
||||||
|
|
||||||
|
default int expectedMaxLength(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
default int expectedMinLength(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,8 @@ import io.netty.handler.codec.CorruptedFrameException;
|
|||||||
import io.netty.handler.codec.DecoderException;
|
import io.netty.handler.codec.DecoderException;
|
||||||
import io.netty.handler.codec.EncoderException;
|
import io.netty.handler.codec.EncoderException;
|
||||||
|
|
||||||
|
import java.io.DataInput;
|
||||||
|
import java.io.DataOutput;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -227,11 +229,12 @@ public enum ProtocolUtils {
|
|||||||
/**
|
/**
|
||||||
* Reads a {@link net.kyori.adventure.nbt.CompoundBinaryTag} from the {@code buf}.
|
* Reads a {@link net.kyori.adventure.nbt.CompoundBinaryTag} from the {@code buf}.
|
||||||
* @param buf the buffer to read from
|
* @param buf the buffer to read from
|
||||||
|
* @param reader the NBT reader to use
|
||||||
* @return {@link net.kyori.adventure.nbt.CompoundBinaryTag} the CompoundTag from the buffer
|
* @return {@link net.kyori.adventure.nbt.CompoundBinaryTag} the CompoundTag from the buffer
|
||||||
*/
|
*/
|
||||||
public static CompoundBinaryTag readCompoundTag(ByteBuf buf) {
|
public static CompoundBinaryTag readCompoundTag(ByteBuf buf, BinaryTagIO.Reader reader) {
|
||||||
try {
|
try {
|
||||||
return BinaryTagIO.readDataInput(new ByteBufInputStream(buf));
|
return reader.read((DataInput) new ByteBufInputStream(buf));
|
||||||
} catch (IOException thrown) {
|
} catch (IOException thrown) {
|
||||||
throw new DecoderException(
|
throw new DecoderException(
|
||||||
"Unable to parse NBT CompoundTag, full error: " + thrown.getMessage());
|
"Unable to parse NBT CompoundTag, full error: " + thrown.getMessage());
|
||||||
@ -245,7 +248,7 @@ public enum ProtocolUtils {
|
|||||||
*/
|
*/
|
||||||
public static void writeCompoundTag(ByteBuf buf, CompoundBinaryTag compoundTag) {
|
public static void writeCompoundTag(ByteBuf buf, CompoundBinaryTag compoundTag) {
|
||||||
try {
|
try {
|
||||||
BinaryTagIO.writeDataOutput(compoundTag, new ByteBufOutputStream(buf));
|
BinaryTagIO.writer().write(compoundTag, (DataOutput) new ByteBufOutputStream(buf));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new EncoderException("Unable to encode NBT CompoundTag");
|
throw new EncoderException("Unable to encode NBT CompoundTag");
|
||||||
}
|
}
|
||||||
|
@ -58,6 +58,8 @@ public class MinecraftDecoder extends ChannelInboundHandlerAdapter {
|
|||||||
ctx.fireChannelRead(buf);
|
ctx.fireChannelRead(buf);
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
|
doLengthSanityChecks(buf, packet);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
packet.decode(buf, direction, registry.version);
|
packet.decode(buf, direction, registry.version);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -65,7 +67,7 @@ public class MinecraftDecoder extends ChannelInboundHandlerAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (buf.isReadable()) {
|
if (buf.isReadable()) {
|
||||||
throw handleNotReadEnough(packet, packetId);
|
throw handleOverflow(packet, buf.readerIndex(), buf.writerIndex());
|
||||||
}
|
}
|
||||||
ctx.fireChannelRead(packet);
|
ctx.fireChannelRead(packet);
|
||||||
} finally {
|
} finally {
|
||||||
@ -74,10 +76,30 @@ public class MinecraftDecoder extends ChannelInboundHandlerAdapter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Exception handleNotReadEnough(MinecraftPacket packet, int packetId) {
|
private void doLengthSanityChecks(ByteBuf buf, MinecraftPacket packet) throws Exception {
|
||||||
|
int expectedMinLen = packet.expectedMinLength(buf, direction, registry.version);
|
||||||
|
int expectedMaxLen = packet.expectedMaxLength(buf, direction, registry.version);
|
||||||
|
if (expectedMaxLen != -1 && buf.readableBytes() > expectedMaxLen) {
|
||||||
|
throw handleOverflow(packet, expectedMaxLen, buf.readableBytes());
|
||||||
|
}
|
||||||
|
if (buf.readableBytes() < expectedMinLen) {
|
||||||
|
throw handleUnderflow(packet, expectedMaxLen, buf.readableBytes());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Exception handleOverflow(MinecraftPacket packet, int expected, int actual) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
return new CorruptedFrameException("Did not read full packet for " + packet.getClass() + " "
|
return new CorruptedFrameException("Packet sent for " + packet.getClass() + " was too "
|
||||||
+ getExtraConnectionDetail(packetId));
|
+ "big (expected " + expected + " bytes, got " + actual + " bytes)");
|
||||||
|
} else {
|
||||||
|
return DECODE_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Exception handleUnderflow(MinecraftPacket packet, int expected, int actual) {
|
||||||
|
if (DEBUG) {
|
||||||
|
return new CorruptedFrameException("Packet sent for " + packet.getClass() + " was too "
|
||||||
|
+ "small (expected " + expected + " bytes, got " + actual + " bytes)");
|
||||||
} else {
|
} else {
|
||||||
return DECODE_FAILED;
|
return DECODE_FAILED;
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import com.velocitypowered.api.network.ProtocolVersion;
|
|||||||
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
|
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
|
||||||
import com.velocitypowered.proxy.protocol.MinecraftPacket;
|
import com.velocitypowered.proxy.protocol.MinecraftPacket;
|
||||||
import com.velocitypowered.proxy.protocol.ProtocolUtils;
|
import com.velocitypowered.proxy.protocol.ProtocolUtils;
|
||||||
|
import com.velocitypowered.proxy.protocol.ProtocolUtils.Direction;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
@ -33,7 +34,7 @@ public class EncryptionResponse implements MinecraftPacket {
|
|||||||
@Override
|
@Override
|
||||||
public void decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) {
|
public void decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) {
|
||||||
if (version.compareTo(ProtocolVersion.MINECRAFT_1_8) >= 0) {
|
if (version.compareTo(ProtocolVersion.MINECRAFT_1_8) >= 0) {
|
||||||
this.sharedSecret = ProtocolUtils.readByteArray(buf, 256);
|
this.sharedSecret = ProtocolUtils.readByteArray(buf, 128);
|
||||||
this.verifyToken = ProtocolUtils.readByteArray(buf, 128);
|
this.verifyToken = ProtocolUtils.readByteArray(buf, 128);
|
||||||
} else {
|
} else {
|
||||||
this.sharedSecret = ProtocolUtils.readByteArray17(buf);
|
this.sharedSecret = ProtocolUtils.readByteArray17(buf);
|
||||||
@ -56,4 +57,16 @@ public class EncryptionResponse implements MinecraftPacket {
|
|||||||
public boolean handle(MinecraftSessionHandler handler) {
|
public boolean handle(MinecraftSessionHandler handler) {
|
||||||
return handler.handle(this);
|
return handler.handle(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int expectedMaxLength(ByteBuf buf, Direction direction, ProtocolVersion version) {
|
||||||
|
// It turns out these come out to the same length, whether we're talking >=1.8 or not.
|
||||||
|
// The length prefix always winds up being 2 bytes.
|
||||||
|
return 260;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int expectedMinLength(ByteBuf buf, Direction direction, ProtocolVersion version) {
|
||||||
|
return expectedMaxLength(buf, direction, version);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import com.velocitypowered.proxy.connection.registry.DimensionInfo;
|
|||||||
import com.velocitypowered.proxy.connection.registry.DimensionRegistry;
|
import com.velocitypowered.proxy.connection.registry.DimensionRegistry;
|
||||||
import com.velocitypowered.proxy.protocol.*;
|
import com.velocitypowered.proxy.protocol.*;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import net.kyori.adventure.nbt.BinaryTagIO;
|
||||||
import net.kyori.adventure.nbt.BinaryTagTypes;
|
import net.kyori.adventure.nbt.BinaryTagTypes;
|
||||||
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
import net.kyori.adventure.nbt.ListBinaryTag;
|
import net.kyori.adventure.nbt.ListBinaryTag;
|
||||||
@ -15,6 +16,7 @@ import org.checkerframework.checker.nullness.qual.Nullable;
|
|||||||
|
|
||||||
public class JoinGame implements MinecraftPacket {
|
public class JoinGame implements MinecraftPacket {
|
||||||
|
|
||||||
|
private static final BinaryTagIO.Reader JOINGAME_READER = BinaryTagIO.reader(2 * 1024 * 1024);
|
||||||
private int entityId;
|
private int entityId;
|
||||||
private short gamemode;
|
private short gamemode;
|
||||||
private int dimension;
|
private int dimension;
|
||||||
@ -178,7 +180,7 @@ public class JoinGame implements MinecraftPacket {
|
|||||||
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16) >= 0) {
|
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16) >= 0) {
|
||||||
this.previousGamemode = buf.readByte();
|
this.previousGamemode = buf.readByte();
|
||||||
ImmutableSet<String> levelNames = ImmutableSet.copyOf(ProtocolUtils.readStringArray(buf));
|
ImmutableSet<String> levelNames = ImmutableSet.copyOf(ProtocolUtils.readStringArray(buf));
|
||||||
CompoundBinaryTag registryContainer = ProtocolUtils.readCompoundTag(buf);
|
CompoundBinaryTag registryContainer = ProtocolUtils.readCompoundTag(buf, JOINGAME_READER);
|
||||||
ListBinaryTag dimensionRegistryContainer = null;
|
ListBinaryTag dimensionRegistryContainer = null;
|
||||||
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0) {
|
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0) {
|
||||||
dimensionRegistryContainer = registryContainer.getCompound("minecraft:dimension_type")
|
dimensionRegistryContainer = registryContainer.getCompound("minecraft:dimension_type")
|
||||||
@ -192,7 +194,7 @@ public class JoinGame implements MinecraftPacket {
|
|||||||
DimensionRegistry.fromGameData(dimensionRegistryContainer, version);
|
DimensionRegistry.fromGameData(dimensionRegistryContainer, version);
|
||||||
this.dimensionRegistry = new DimensionRegistry(readData, levelNames);
|
this.dimensionRegistry = new DimensionRegistry(readData, levelNames);
|
||||||
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0) {
|
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0) {
|
||||||
CompoundBinaryTag currentDimDataTag = ProtocolUtils.readCompoundTag(buf);
|
CompoundBinaryTag currentDimDataTag = ProtocolUtils.readCompoundTag(buf, JOINGAME_READER);
|
||||||
dimensionIdentifier = ProtocolUtils.readString(buf);
|
dimensionIdentifier = ProtocolUtils.readString(buf);
|
||||||
this.currentDimensionData = DimensionData.decodeBaseCompoundTag(currentDimDataTag, version)
|
this.currentDimensionData = DimensionData.decodeBaseCompoundTag(currentDimDataTag, version)
|
||||||
.annotateWith(dimensionIdentifier, null);
|
.annotateWith(dimensionIdentifier, null);
|
||||||
|
@ -7,6 +7,7 @@ import com.velocitypowered.proxy.connection.registry.DimensionInfo;
|
|||||||
import com.velocitypowered.proxy.protocol.MinecraftPacket;
|
import com.velocitypowered.proxy.protocol.MinecraftPacket;
|
||||||
import com.velocitypowered.proxy.protocol.ProtocolUtils;
|
import com.velocitypowered.proxy.protocol.ProtocolUtils;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import net.kyori.adventure.nbt.BinaryTagIO;
|
||||||
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||||
|
|
||||||
public class Respawn implements MinecraftPacket {
|
public class Respawn implements MinecraftPacket {
|
||||||
@ -116,7 +117,7 @@ public class Respawn implements MinecraftPacket {
|
|||||||
String levelName = null;
|
String levelName = null;
|
||||||
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16) >= 0) {
|
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16) >= 0) {
|
||||||
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0) {
|
if (version.compareTo(ProtocolVersion.MINECRAFT_1_16_2) >= 0) {
|
||||||
CompoundBinaryTag dimDataTag = ProtocolUtils.readCompoundTag(buf);
|
CompoundBinaryTag dimDataTag = ProtocolUtils.readCompoundTag(buf, BinaryTagIO.reader());
|
||||||
dimensionIdentifier = ProtocolUtils.readString(buf);
|
dimensionIdentifier = ProtocolUtils.readString(buf);
|
||||||
this.currentDimensionData = DimensionData.decodeBaseCompoundTag(dimDataTag, version)
|
this.currentDimensionData = DimensionData.decodeBaseCompoundTag(dimDataTag, version)
|
||||||
.annotateWith(dimensionIdentifier, null);
|
.annotateWith(dimensionIdentifier, null);
|
||||||
|
@ -5,6 +5,7 @@ import com.velocitypowered.api.network.ProtocolVersion;
|
|||||||
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
|
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
|
||||||
import com.velocitypowered.proxy.protocol.MinecraftPacket;
|
import com.velocitypowered.proxy.protocol.MinecraftPacket;
|
||||||
import com.velocitypowered.proxy.protocol.ProtocolUtils;
|
import com.velocitypowered.proxy.protocol.ProtocolUtils;
|
||||||
|
import com.velocitypowered.proxy.protocol.ProtocolUtils.Direction;
|
||||||
import com.velocitypowered.proxy.util.except.QuietDecoderException;
|
import com.velocitypowered.proxy.util.except.QuietDecoderException;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
@ -52,6 +53,13 @@ public class ServerLogin implements MinecraftPacket {
|
|||||||
ProtocolUtils.writeString(buf, username);
|
ProtocolUtils.writeString(buf, username);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int expectedMaxLength(ByteBuf buf, Direction direction, ProtocolVersion version) {
|
||||||
|
// Accommodate the rare (but likely malicious) use of UTF-8 usernames, since it is technically
|
||||||
|
// legal on the protocol level.
|
||||||
|
return 1 + (16 * 4);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean handle(MinecraftSessionHandler handler) {
|
public boolean handle(MinecraftSessionHandler handler) {
|
||||||
return handler.handle(this);
|
return handler.handle(this);
|
||||||
|
@ -4,6 +4,7 @@ import com.velocitypowered.api.network.ProtocolVersion;
|
|||||||
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
|
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
|
||||||
import com.velocitypowered.proxy.protocol.MinecraftPacket;
|
import com.velocitypowered.proxy.protocol.MinecraftPacket;
|
||||||
import com.velocitypowered.proxy.protocol.ProtocolUtils;
|
import com.velocitypowered.proxy.protocol.ProtocolUtils;
|
||||||
|
import com.velocitypowered.proxy.protocol.ProtocolUtils.Direction;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
|
|
||||||
public class StatusPing implements MinecraftPacket {
|
public class StatusPing implements MinecraftPacket {
|
||||||
@ -24,4 +25,14 @@ public class StatusPing implements MinecraftPacket {
|
|||||||
public boolean handle(MinecraftSessionHandler handler) {
|
public boolean handle(MinecraftSessionHandler handler) {
|
||||||
return handler.handle(this);
|
return handler.handle(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int expectedMaxLength(ByteBuf buf, Direction direction, ProtocolVersion version) {
|
||||||
|
return 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int expectedMinLength(ByteBuf buf, Direction direction, ProtocolVersion version) {
|
||||||
|
return 8;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import com.velocitypowered.api.network.ProtocolVersion;
|
|||||||
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
|
import com.velocitypowered.proxy.connection.MinecraftSessionHandler;
|
||||||
import com.velocitypowered.proxy.protocol.MinecraftPacket;
|
import com.velocitypowered.proxy.protocol.MinecraftPacket;
|
||||||
import com.velocitypowered.proxy.protocol.ProtocolUtils;
|
import com.velocitypowered.proxy.protocol.ProtocolUtils;
|
||||||
|
import com.velocitypowered.proxy.protocol.ProtocolUtils.Direction;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
|
|
||||||
public class StatusRequest implements MinecraftPacket {
|
public class StatusRequest implements MinecraftPacket {
|
||||||
@ -33,4 +34,9 @@ public class StatusRequest implements MinecraftPacket {
|
|||||||
public boolean handle(MinecraftSessionHandler handler) {
|
public boolean handle(MinecraftSessionHandler handler) {
|
||||||
return handler.handle(this);
|
return handler.handle(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int expectedMaxLength(ByteBuf buf, Direction direction, ProtocolVersion version) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ bind = "0.0.0.0:25577"
|
|||||||
|
|
||||||
# What should be the MOTD? This gets displayed when the player adds your server to
|
# What should be the MOTD? This gets displayed when the player adds your server to
|
||||||
# their server list. Legacy color codes and JSON are accepted.
|
# their server list. Legacy color codes and JSON are accepted.
|
||||||
motd = "&3A Velocity Server"
|
motd = "	add3A Velocity Server"
|
||||||
|
|
||||||
# What should we display for the maximum number of players? (Velocity does not support a cap
|
# What should we display for the maximum number of players? (Velocity does not support a cap
|
||||||
# on the number of players online.)
|
# on the number of players online.)
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren