Made packet intercepting possible

This commit is contained in:
LOOHP 2022-02-10 01:54:13 +00:00
parent 00600647ae
commit 4353859951
11 changed files with 346 additions and 109 deletions

View File

@ -5,7 +5,7 @@
<groupId>com.loohp</groupId>
<artifactId>Limbo</artifactId>
<name>Limbo</name>
<version>0.6.10-ALPHA</version>
<version>0.6.11-ALPHA</version>
<description>Standalone Limbo Minecraft Server.</description>
<url>https://github.com/LOOHP/Limbo</url>
@ -230,7 +230,7 @@
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-chat</artifactId>
<version>1.17-R0.1-SNAPSHOT</version>
<version>1.18-R0.1-SNAPSHOT</version>
<type>jar</type>
<scope>compile</scope>
</dependency>

View File

@ -1,5 +1,155 @@
package com.loohp.limbo.network;
public class Channel {
import com.loohp.limbo.network.protocol.packets.Packet;
import com.loohp.limbo.network.protocol.packets.PacketIn;
import com.loohp.limbo.network.protocol.packets.PacketOut;
import com.loohp.limbo.utils.DataTypeIO;
import com.loohp.limbo.utils.NamespacedKey;
import com.loohp.limbo.utils.Pair;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Stream;
public class Channel implements AutoCloseable {
private final ClientConnection clientConnection;
private final List<Pair<NamespacedKey, ChannelPacketHandler>> handlers;
private final AtomicBoolean valid;
protected DataOutputStream output;
protected DataInputStream input;
public Channel(ClientConnection clientConnection, DataOutputStream output, DataInputStream input) {
this.clientConnection = clientConnection;
this.output = output;
this.input = input;
this.handlers = new CopyOnWriteArrayList<>();
this.valid = new AtomicBoolean(true);
}
private void ensureOpen() {
if (!valid.get()) {
throw new IllegalStateException("Channel already closed!");
}
}
public void addBefore(NamespacedKey key, ChannelPacketHandler handler) {
handlers.add(0, new Pair<>(key, handler));
}
public void addAfter(NamespacedKey key, ChannelPacketHandler handler) {
handlers.add(new Pair<>(key, handler));
}
public void remove(NamespacedKey key) {
handlers.removeIf(each -> each.getFirst().equals(key));
}
protected PacketIn readPacket() throws Exception {
return readPacket(-1);
}
protected PacketIn readPacket(int size) throws Exception {
PacketIn packet = null;
do {
ensureOpen();
size = size < 0 ? DataTypeIO.readVarInt(input) : size;
int packetId = DataTypeIO.readVarInt(input);
Class<? extends PacketIn> packetType;
switch (clientConnection.getClientState()) {
case HANDSHAKE:
packetType = Packet.getHandshakeIn().get(packetId);
break;
case STATUS:
packetType = Packet.getStatusIn().get(packetId);
break;
case LOGIN:
packetType = Packet.getLoginIn().get(packetId);
break;
case PLAY:
packetType = Packet.getPlayIn().get(packetId);
break;
default:
throw new IllegalStateException("Illegal ClientState!");
}
if (packetType == null) {
input.skipBytes(size - DataTypeIO.getVarIntLength(packetId));
} else {
Constructor<?>[] constructors = packetType.getConstructors();
Constructor<?> constructor = Stream.of(constructors).filter(each -> each.getParameterCount() > 0 && each.getParameterTypes()[0].equals(DataInputStream.class)).findFirst().orElse(null);
if (constructor == null) {
throw new NoSuchMethodException(packetType + " has no valid constructors!");
} else if (constructor.getParameterCount() == 1) {
packet = (PacketIn) constructor.newInstance(input);
} else if (constructor.getParameterCount() == 3) {
packet = (PacketIn) constructor.newInstance(input, size, packetId);
} else {
throw new NoSuchMethodException(packetType + " has no valid constructors!");
}
ChannelPacketRead read = new ChannelPacketRead(packetId, packet);
for (Pair<NamespacedKey, ChannelPacketHandler> pair : handlers) {
read = pair.getSecond().read(read);
if (read == null) {
packet = null;
break;
}
packet = read.getPacket();
if (!packetType.isInstance(packet)) {
throw new IllegalStateException("Packet Handler \"" + pair.getFirst() + "\" changed the packet type illegally!");
}
}
}
size = -1;
} while (packet == null);
return packet;
}
protected boolean writePacket(PacketOut packet) throws IOException {
ensureOpen();
int packetId;
switch (clientConnection.getClientState()) {
case STATUS:
packetId = Packet.getStatusOut().get(packet.getClass());
break;
case LOGIN:
packetId = Packet.getLoginOut().get(packet.getClass());
break;
case PLAY:
packetId = Packet.getPlayOut().get(packet.getClass());
break;
default:
throw new IllegalStateException("Illegal ClientState!");
}
Class<? extends PacketOut> packetType = packet.getClass();
ChannelPacketWrite write = new ChannelPacketWrite(packet);
for (Pair<NamespacedKey, ChannelPacketHandler> pair : handlers) {
write = pair.getSecond().write(write);
if (write == null) {
return false;
}
if (!packetType.isInstance(write.getPacket())) {
throw new IllegalStateException("Packet Handler \"" + pair.getFirst() + "\" changed the packet type illegally!");
}
}
packet = write.getPacket();
byte[] packetByte = packet.serializePacket();
DataTypeIO.writeVarInt(output, packetByte.length);
output.write(packetByte);
output.flush();
return true;
}
@Override
public synchronized void close() throws Exception {
if (valid.compareAndSet(false, true)) {
input.close();
output.close();
}
}
}

View File

@ -0,0 +1,13 @@
package com.loohp.limbo.network;
public abstract class ChannelPacketHandler {
public ChannelPacketRead read(ChannelPacketRead read) {
return read;
}
public ChannelPacketWrite write(ChannelPacketWrite write) {
return write;
}
}

View File

@ -0,0 +1,31 @@
package com.loohp.limbo.network;
import com.loohp.limbo.network.protocol.packets.PacketIn;
public final class ChannelPacketRead {
private int packetId;
private PacketIn packet;
protected ChannelPacketRead(int packetId, PacketIn packet) {
this.packetId = packetId;
this.packet = packet;
}
public int getPacketId() {
return packetId;
}
public void setPacketId(int packetId) {
this.packetId = packetId;
}
public PacketIn getPacket() {
return packet;
}
public void setPacket(PacketIn packet) {
this.packet = packet;
}
}

View File

@ -0,0 +1,21 @@
package com.loohp.limbo.network;
import com.loohp.limbo.network.protocol.packets.PacketOut;
public final class ChannelPacketWrite {
private PacketOut packet;
protected ChannelPacketWrite(PacketOut packet) {
this.packet = packet;
}
public PacketOut getPacket() {
return packet;
}
public void setPacket(PacketOut packet) {
this.packet = packet;
}
}

View File

@ -19,6 +19,7 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;
import com.loohp.limbo.network.protocol.packets.PacketIn;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
@ -113,9 +114,8 @@ public class ClientConnection extends Thread {
private TimerTask keepAliveTask;
private AtomicLong lastPacketTimestamp;
private AtomicLong lastKeepAlivePayLoad;
private DataOutputStream output;
private DataInputStream input;
protected Channel channel;
private InetAddress inetAddress;
@ -126,6 +126,7 @@ public class ClientConnection extends Thread {
this.inetAddress = client_socket.getInetAddress();
this.lastPacketTimestamp = new AtomicLong(-1);
this.lastKeepAlivePayLoad = new AtomicLong(-1);
this.channel = new Channel(this, null, null);
this.running = false;
this.ready = false;
}
@ -165,6 +166,10 @@ public class ClientConnection extends Thread {
public Socket getSocket() {
return client_socket;
}
public Channel getChannel() {
return channel;
}
public boolean isRunning() {
return running;
@ -175,11 +180,9 @@ public class ClientConnection extends Thread {
}
public synchronized void sendPacket(PacketOut packet) throws IOException {
byte[] packetByte = packet.serializePacket();
DataTypeIO.writeVarInt(output, packetByte.length);
output.write(packetByte);
output.flush();
setLastPacketTimestamp(System.currentTimeMillis());
if (channel.writePacket(packet)) {
setLastPacketTimestamp(System.currentTimeMillis());
}
}
public void disconnect(BaseComponent[] reason) {
@ -190,10 +193,10 @@ public class ClientConnection extends Thread {
try {
PacketPlayOutDisconnect packet = new PacketPlayOutDisconnect(reason);
sendPacket(packet);
} catch (IOException e) {}
} catch (IOException ignored) {}
try {
client_socket.close();
} catch (IOException e) {}
} catch (IOException ignored) {}
}
private void disconnectDuringLogin(BaseComponent[] reason) {
@ -204,10 +207,10 @@ public class ClientConnection extends Thread {
try {
PacketLoginOutDisconnect packet = new PacketLoginOutDisconnect(reason);
sendPacket(packet);
} catch (IOException e) {}
} catch (IOException ignored) {}
try {
client_socket.close();
} catch (IOException e) {}
} catch (IOException ignored) {}
}
@SuppressWarnings("deprecation")
@ -217,31 +220,29 @@ public class ClientConnection extends Thread {
state = ClientState.HANDSHAKE;
try {
client_socket.setKeepAlive(true);
input = new DataInputStream(client_socket.getInputStream());
output = new DataOutputStream(client_socket.getOutputStream());
int handShakeSize = DataTypeIO.readVarInt(input);
channel.input = new DataInputStream(client_socket.getInputStream());
channel.output = new DataOutputStream(client_socket.getOutputStream());
int handShakeSize = DataTypeIO.readVarInt(channel.input);
//legacy ping
if (handShakeSize == 0xFE) {
state = ClientState.LEGACY;
output.writeByte(255);
state = ClientState.LEGACY;
channel.output.writeByte(255);
String str = inetAddress.getHostName() + ":" + client_socket.getPort();
Limbo.getInstance().getConsole().sendMessage("[/" + str + "] <-> Legacy Status has pinged");
ServerProperties p = Limbo.getInstance().getServerProperties();
StatusPingEvent event = Limbo.getInstance().getEventsManager().callEvent(new StatusPingEvent(this, p.getVersionString(), p.getProtocol(), p.getMotd(), p.getMaxPlayers(), Limbo.getInstance().getPlayers().size(), p.getFavicon().orElse(null)));
String response = Limbo.getInstance().buildLegacyPingResponse(event.getVersion(), event.getMotd(), event.getMaxPlayers(), event.getPlayersOnline());
byte[] bytes = response.getBytes(StandardCharsets.UTF_16BE);
output.writeShort(response.length());
output.write(bytes);
channel.output.writeShort(response.length());
channel.output.write(bytes);
channel.close();
client_socket.close();
state = ClientState.DISCONNECTED;
}
@SuppressWarnings("unused")
int handShakeId = DataTypeIO.readVarInt(input);
PacketHandshakingIn handshake = new PacketHandshakingIn(input);
PacketHandshakingIn handshake = (PacketHandshakingIn) channel.readPacket(handShakeSize);
boolean isBungeecord = Limbo.getInstance().getServerProperties().isBungeecord();
boolean isBungeeGuard = Limbo.getInstance().getServerProperties().isBungeeGuard();
@ -255,24 +256,20 @@ public class ClientConnection extends Thread {
case STATUS:
state = ClientState.STATUS;
while (client_socket.isConnected()) {
DataTypeIO.readVarInt(input);
int packetId = DataTypeIO.readVarInt(input);
Class<? extends Packet> packetType = Packet.getStatusIn().get(packetId);
if (packetType == null) {
//do nothing
} else if (packetType.equals(PacketStatusInRequest.class)) {
PacketIn packetIn = channel.readPacket();
if (packetIn instanceof PacketStatusInRequest) {
String str = inetAddress.getHostName() + ":" + client_socket.getPort();
if (Limbo.getInstance().getServerProperties().handshakeVerboseEnabled()) {
Limbo.getInstance().getConsole().sendMessage("[/" + str + "] <-> Handshake Status has pinged");
}
ServerProperties p = Limbo.getInstance().getServerProperties();
StatusPingEvent event = Limbo.getInstance().getEventsManager().callEvent(new StatusPingEvent(this, p.getVersionString(), p.getProtocol(), p.getMotd(), p.getMaxPlayers(), Limbo.getInstance().getPlayers().size(), p.getFavicon().orElse(null)));
PacketStatusOutResponse packet = new PacketStatusOutResponse(Limbo.getInstance().buildServerListResponseJson(event.getVersion(), event.getProtocol(), event.getMotd(), event.getMaxPlayers(), event.getPlayersOnline(), event.getFavicon()));
sendPacket(packet);
} else if (packetType.equals(PacketStatusInPing.class)) {
PacketStatusInPing ping = new PacketStatusInPing(input);
PacketStatusOutPong packet = new PacketStatusOutPong(ping.getPayload());
sendPacket(packet);
PacketStatusOutResponse response = new PacketStatusOutResponse(Limbo.getInstance().buildServerListResponseJson(event.getVersion(), event.getProtocol(), event.getMotd(), event.getMaxPlayers(), event.getPlayersOnline(), event.getFavicon()));
sendPacket(response);
} else if (packetIn instanceof PacketStatusInPing) {
PacketStatusInPing ping = (PacketStatusInPing) packetIn;
PacketStatusOutPong pong = new PacketStatusOutPong(ping.getPayload());
sendPacket(pong);
break;
}
}
@ -318,14 +315,9 @@ public class ClientConnection extends Thread {
int messageId = this.random.nextInt();
while (client_socket.isConnected()) {
int size = DataTypeIO.readVarInt(input);
int packetId = DataTypeIO.readVarInt(input);
Class<? extends Packet> packetType = Packet.getLoginIn().get(packetId);
if (packetType == null) {
input.skipBytes(size - DataTypeIO.getVarIntLength(packetId));
} else if (packetType.equals(PacketLoginInLoginStart.class)) {
PacketLoginInLoginStart start = new PacketLoginInLoginStart(input);
PacketIn packetIn = channel.readPacket();
if (packetIn instanceof PacketLoginInLoginStart) {
PacketLoginInLoginStart start = (PacketLoginInLoginStart) packetIn;
String username = start.getUsername();
if (Limbo.getInstance().getServerProperties().isVelocityModern()) {
@ -346,8 +338,8 @@ public class ClientConnection extends Thread {
Limbo.getInstance().addPlayer(player);
break;
} else if (packetType.equals(PacketLoginInPluginMessaging.class)) {
PacketLoginInPluginMessaging response = new PacketLoginInPluginMessaging(input, size, packetId);
} else if (packetIn instanceof PacketLoginInPluginMessaging) {
PacketLoginInPluginMessaging response = (PacketLoginInPluginMessaging) packetIn;
if (response.getMessageId() != messageId) {
disconnectDuringLogin(TextComponent.fromLegacyText("Internal error, messageId did not match"));
break;
@ -375,8 +367,6 @@ public class ClientConnection extends Thread {
Limbo.getInstance().addPlayer(player);
break;
} else {
input.skipBytes(size - DataTypeIO.getVarIntLength(packetId));
}
}
@ -388,6 +378,7 @@ public class ClientConnection extends Thread {
break;
}
} catch (Exception e) {
channel.close();
client_socket.close();
state = ClientState.DISCONNECTED;
}
@ -487,10 +478,6 @@ public class ClientConnection extends Thread {
while (client_socket.isConnected()) {
try {
int size = DataTypeIO.readVarInt(input);
int packetId = DataTypeIO.readVarInt(input);
Class<? extends Packet> packetType = Packet.getPlayIn().get(packetId);
//Limbo.getInstance().getConsole().sendMessage(packetId + " -> " + packetType);
CheckedBiConsumer<PlayerMoveEvent, Location, IOException> processMoveEvent = (event, originalTo) -> {
if (event.isCancelled()) {
Location returnTo = event.getFrom();
@ -508,10 +495,9 @@ public class ClientConnection extends Thread {
sendPacket(response);
}
};
if (packetType == null) {
input.skipBytes(size - DataTypeIO.getVarIntLength(packetId));
} else if (packetType.equals(PacketPlayInPositionAndLook.class)) {
PacketPlayInPositionAndLook pos = new PacketPlayInPositionAndLook(input);
PacketIn packetIn = channel.readPacket();
if (packetIn instanceof PacketPlayInPositionAndLook) {
PacketPlayInPositionAndLook pos = (PacketPlayInPositionAndLook) packetIn;
Location from = player.getLocation();
Location to = new Location(player.getWorld(), pos.getX(), pos.getY(), pos.getZ(), pos.getYaw(), pos.getPitch());
@ -519,8 +505,8 @@ public class ClientConnection extends Thread {
PlayerMoveEvent event = Limbo.getInstance().getEventsManager().callEvent(new PlayerMoveEvent(player, from, to));
processMoveEvent.consume(event, to);
}
} else if (packetType.equals(PacketPlayInPosition.class)) {
PacketPlayInPosition pos = new PacketPlayInPosition(input);
} else if (packetIn instanceof PacketPlayInPosition) {
PacketPlayInPosition pos = (PacketPlayInPosition) packetIn;
Location from = player.getLocation();
Location to = new Location(player.getWorld(), pos.getX(), pos.getY(), pos.getZ(), player.getLocation().getYaw(), player.getLocation().getPitch());
@ -528,8 +514,8 @@ public class ClientConnection extends Thread {
PlayerMoveEvent event = Limbo.getInstance().getEventsManager().callEvent(new PlayerMoveEvent(player, from, to));
processMoveEvent.consume(event, to);
}
} else if (packetType.equals(PacketPlayInRotation.class)) {
PacketPlayInRotation pos = new PacketPlayInRotation(input);
} else if (packetIn instanceof PacketPlayInRotation) {
PacketPlayInRotation pos = (PacketPlayInRotation) packetIn;
Location from = player.getLocation();
Location to = new Location(player.getWorld(), player.getLocation().getX(), player.getLocation().getY(), player.getLocation().getZ(), pos.getYaw(), pos.getPitch());
@ -537,34 +523,32 @@ public class ClientConnection extends Thread {
PlayerMoveEvent event = Limbo.getInstance().getEventsManager().callEvent(new PlayerMoveEvent(player, from, to));
processMoveEvent.consume(event, to);
}
} else if (packetType.equals(PacketPlayInKeepAlive.class)) {
PacketPlayInKeepAlive alive = new PacketPlayInKeepAlive(input);
} else if (packetIn instanceof PacketPlayInKeepAlive) {
PacketPlayInKeepAlive alive = (PacketPlayInKeepAlive) packetIn;
if (alive.getPayload() != getLastKeepAlivePayLoad()) {
Limbo.getInstance().getConsole().sendMessage("Incorrect Payload recieved in KeepAlive packet for player " + player.getName());
Limbo.getInstance().getConsole().sendMessage("Incorrect Payload received in KeepAlive packet for player " + player.getName());
break;
}
} else if (packetType.equals(PacketPlayInTabComplete.class)) {
PacketPlayInTabComplete request = new PacketPlayInTabComplete(input);
} else if (packetIn instanceof PacketPlayInTabComplete) {
PacketPlayInTabComplete request = (PacketPlayInTabComplete) packetIn;
String[] command = CustomStringUtils.splitStringToArgs(request.getText().substring(1));
List<TabCompleteMatches> matches = new ArrayList<TabCompleteMatches>();
matches.addAll(Limbo.getInstance().getPluginManager().getTabOptions(player, command).stream().map(each -> new TabCompleteMatches(each)).collect(Collectors.toList()));
List<TabCompleteMatches> matches = new ArrayList<TabCompleteMatches>(Limbo.getInstance().getPluginManager().getTabOptions(player, command).stream().map(each -> new TabCompleteMatches(each)).collect(Collectors.toList()));
int start = CustomStringUtils.getIndexOfArg(request.getText(), command.length - 1) + 1;
int length = command[command.length - 1].length();
PacketPlayOutTabComplete response = new PacketPlayOutTabComplete(request.getId(), start, length, matches.toArray(new TabCompleteMatches[matches.size()]));
sendPacket(response);
} else if (packetType.equals(PacketPlayInChat.class)) {
PacketPlayInChat chat = new PacketPlayInChat(input);
} else if (packetIn instanceof PacketPlayInChat) {
PacketPlayInChat chat = (PacketPlayInChat) packetIn;
if (chat.getMessage().startsWith("/")) {
Limbo.getInstance().dispatchCommand(player, chat.getMessage());
} else {
player.chat(chat.getMessage(), true);
}
} else if (packetType.equals(PacketPlayInHeldItemChange.class)) {
PacketPlayInHeldItemChange change = new PacketPlayInHeldItemChange(input);
} else if (packetIn instanceof PacketPlayInHeldItemChange) {
PacketPlayInHeldItemChange change = (PacketPlayInHeldItemChange) packetIn;
PlayerSelectedSlotChangeEvent event = Limbo.getInstance().getEventsManager().callEvent(new PlayerSelectedSlotChangeEvent(player, (byte) change.getSlot()));
if (event.isCancelled()) {
PacketPlayOutHeldItemChange cancelPacket = new PacketPlayOutHeldItemChange(player.getSelectedSlot());
@ -577,17 +561,14 @@ public class ClientConnection extends Thread {
Limbo.getInstance().getUnsafe().setSelectedSlotSilently(player, event.getSlot());
}
} else if (packetType.equals(PacketPlayInResourcePackStatus.class)) {
PacketPlayInResourcePackStatus rpcheck = new PacketPlayInResourcePackStatus(input);
} else if (packetIn instanceof PacketPlayInResourcePackStatus) {
PacketPlayInResourcePackStatus rpcheck = (PacketPlayInResourcePackStatus) packetIn;
// Pass on result to the events
Limbo.getInstance().getEventsManager().callEvent(new PlayerResourcePackStatusEvent(player, rpcheck.getLoadedValue()));
if (rpcheck.getLoadedValue().equals(EnumResourcePackStatus.DECLINED) && properties.getResourcePackRequired()) {
player.disconnect(new TranslatableComponent("multiplayer.requiredTexturePrompt.disconnect"));
}
} else {
input.skipBytes(size - DataTypeIO.getVarIntLength(packetId));
}
} catch (Exception e) {
break;
}
@ -600,11 +581,12 @@ public class ClientConnection extends Thread {
}
} catch (Exception e) {}
} catch (Exception ignored) {}
try {
channel.close();
client_socket.close();
} catch (IOException e) {}
} catch (Exception ignored) {}
state = ClientState.DISCONNECTED;
if (player != null) {

View File

@ -4,71 +4,71 @@ import java.util.Map;
public class Packet {
private static Map<Integer, Class<? extends PacketIn>> HandshakeIn;
private static Map<Integer, Class<? extends PacketIn>> handshakeIn;
private static Map<Integer, Class<? extends PacketIn>> StatusIn;
private static Map<Class<? extends PacketOut>, Integer> StatusOut;
private static Map<Integer, Class<? extends PacketIn>> statusIn;
private static Map<Class<? extends PacketOut>, Integer> statusOut;
private static Map<Integer, Class<? extends PacketIn>> LoginIn;
private static Map<Class<? extends PacketOut>, Integer> LoginOut;
private static Map<Integer, Class<? extends PacketIn>> loginIn;
private static Map<Class<? extends PacketOut>, Integer> loginOut;
private static Map<Integer, Class<? extends PacketIn>> PlayIn;
private static Map<Class<? extends PacketOut>, Integer> PlayOut;
private static Map<Integer, Class<? extends PacketIn>> playIn;
private static Map<Class<? extends PacketOut>, Integer> playOut;
public static Map<Integer, Class<? extends PacketIn>> getHandshakeIn() {
return HandshakeIn;
return handshakeIn;
}
public static void setHandshakeIn(Map<Integer, Class<? extends PacketIn>> handshakeIn) {
HandshakeIn = handshakeIn;
Packet.handshakeIn = handshakeIn;
}
public static Map<Integer, Class<? extends PacketIn>> getStatusIn() {
return StatusIn;
return statusIn;
}
public static void setStatusIn(Map<Integer, Class<? extends PacketIn>> statusIn) {
StatusIn = statusIn;
Packet.statusIn = statusIn;
}
public static Map<Class<? extends PacketOut>, Integer> getStatusOut() {
return StatusOut;
return statusOut;
}
public static void setStatusOut(Map<Class<? extends PacketOut>, Integer> statusOut) {
StatusOut = statusOut;
Packet.statusOut = statusOut;
}
public static Map<Integer, Class<? extends PacketIn>> getLoginIn() {
return LoginIn;
return loginIn;
}
public static void setLoginIn(Map<Integer, Class<? extends PacketIn>> loginIn) {
LoginIn = loginIn;
Packet.loginIn = loginIn;
}
public static Map<Class<? extends PacketOut>, Integer> getLoginOut() {
return LoginOut;
return loginOut;
}
public static void setLoginOut(Map<Class<? extends PacketOut>, Integer> loginOut) {
LoginOut = loginOut;
Packet.loginOut = loginOut;
}
public static Map<Integer, Class<? extends PacketIn>> getPlayIn() {
return PlayIn;
return playIn;
}
public static void setPlayIn(Map<Integer, Class<? extends PacketIn>> playIn) {
PlayIn = playIn;
Packet.playIn = playIn;
}
public static Map<Class<? extends PacketOut>, Integer> getPlayOut() {
return PlayOut;
return playOut;
}
public static void setPlayOut(Map<Class<? extends PacketOut>, Integer> playOut) {
PlayOut = playOut;
Packet.playOut = playOut;
}
}

View File

@ -22,7 +22,7 @@ public class PacketPlayInPluginMessaging extends PacketIn {
channel = new NamespacedKey(rawChannel);
int dataLength = packetLength - DataTypeIO.getVarIntLength(packetId) - DataTypeIO.getStringLength(rawChannel, StandardCharsets.UTF_8);
data = new byte[dataLength];
in.read(data);
in.readFully(data);
}
public NamespacedKey getChannel() {

View File

@ -52,7 +52,7 @@ public class DataTypeIO {
public static int getStringLength(String string, Charset charset) throws IOException {
byte[] bytes = string.getBytes(charset);
return bytes.length;
return getVarIntLength(bytes.length) + bytes.length;
}
public static void writeString(DataOutputStream out, String string, Charset charset) throws IOException {

View File

@ -0,0 +1,40 @@
package com.loohp.limbo.utils;
import java.util.Objects;
public class Pair<F, S> {
private final F first;
private final S second;
public Pair(F first, S second) {
this.first = first;
this.second = second;
}
public F getFirst() {
return first;
}
public S getSecond() {
return second;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Pair<?, ?> pair = (Pair<?, ?>) o;
return Objects.equals(first, pair.first) && Objects.equals(second, pair.second);
}
@Override
public int hashCode() {
return Objects.hash(first, second);
}
}

View File

@ -46,7 +46,7 @@
"PacketPlayOutHeldItemChange": "0x48",
"PacketPlayOutPlayerListHeaderFooter": "0x5F",
"PacketPlayOutResourcePackSend": "0x3C",
"ClientboundSetTitlesAnimationPacket": "0x5B",
"ClientboundSetTitlesAnimationPacket": "0x5B",
"ClientboundSetTitleTextPacket": "0x5A",
"ClientboundSetSubtitleTextPacket": "0x58",
"ClientboundClearTitlesPacket": "0x10"
@ -59,4 +59,4 @@
"PacketStatusOutResponse": "0x00",
"PacketStatusOutPong": "0x01"
}
}
}