Add Chat packet

This commit is contained in:
Andrew Steinborn 2018-07-25 14:43:10 -04:00
parent 2e250d24b6
commit bd926eb174
5 changed files with 94 additions and 12 deletions

View File

@ -23,6 +23,9 @@ public enum StateRegistry {
}, },
PLAY { PLAY {
{ {
TO_SERVER.register(0x02, Chat.class, Chat::new);
TO_CLIENT.register(0x0F, Chat.class, Chat::new);
TO_CLIENT.register(0x1A, Disconnect.class, Disconnect::new); TO_CLIENT.register(0x1A, Disconnect.class, Disconnect::new);
} }
}, },

View File

@ -0,0 +1,51 @@
package io.minimum.minecraft.velocity.protocol.packets;
import io.minimum.minecraft.velocity.protocol.MinecraftPacket;
import io.minimum.minecraft.velocity.protocol.ProtocolConstants;
import io.minimum.minecraft.velocity.protocol.ProtocolUtils;
import io.netty.buffer.ByteBuf;
public class Chat implements MinecraftPacket {
private String message;
private byte position;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public byte getPosition() {
return position;
}
public void setPosition(byte position) {
this.position = position;
}
@Override
public String toString() {
return "Chat{" +
"message='" + message + '\'' +
", position=" + position +
'}';
}
@Override
public void decode(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) {
message = ProtocolUtils.readString(buf);
if (direction == ProtocolConstants.Direction.TO_CLIENT) {
position = buf.readByte();
}
}
@Override
public void encode(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) {
ProtocolUtils.writeString(buf, message);
if (direction == ProtocolConstants.Direction.TO_CLIENT) {
buf.writeByte(position);
}
}
}

View File

@ -1,5 +1,7 @@
package io.minimum.minecraft.velocity.proxy; package io.minimum.minecraft.velocity.proxy;
import io.minimum.minecraft.velocity.data.ServerInfo;
import io.minimum.minecraft.velocity.protocol.packets.Chat;
import io.minimum.minecraft.velocity.protocol.packets.Disconnect; import io.minimum.minecraft.velocity.protocol.packets.Disconnect;
import net.kyori.text.TextComponent; import net.kyori.text.TextComponent;
import net.kyori.text.format.TextColor; import net.kyori.text.format.TextColor;
@ -35,19 +37,30 @@ public class ConnectedPlayer {
return connectedServer; return connectedServer;
} }
public void handleConnectionException(Throwable throwable) { public void handleConnectionException(ServerInfo info, Throwable throwable) {
String error = "Exception: " + throwable.getClass().getName() + ": " + throwable.getMessage(); String error = String.format("%s: %s",
throwable.getClass().getName(), throwable.getMessage());
Disconnect disconnect = new Disconnect(); Disconnect disconnect = new Disconnect();
disconnect.setReason(ComponentSerializers.JSON.serialize(TextComponent.of(error, TextColor.RED))); disconnect.setReason(ComponentSerializers.JSON.serialize(TextComponent.of(error, TextColor.RED)));
handleConnectionException(disconnect); handleConnectionException(info, disconnect);
} }
public void handleConnectionException(Disconnect disconnect) { public void handleConnectionException(ServerInfo info, Disconnect disconnect) {
TextComponent component = TextComponent.builder()
.content("Exception connecting to server " + info.getName() + ": ")
.color(TextColor.RED)
.append(ComponentSerializers.JSON.deserialize(disconnect.getReason()))
.build();
if (connectedServer == null) { if (connectedServer == null) {
// The player isn't yet connected to a server - we should disconnect them. // The player isn't yet connected to a server - we should disconnect them.
connection.closeWith(disconnect); Disconnect d = new Disconnect();
d.setReason(ComponentSerializers.JSON.serialize(component));
connection.closeWith(d);
} else { } else {
// TODO Chat chat = new Chat();
chat.setMessage(ComponentSerializers.JSON.serialize(component));
connection.write(chat);
} }
} }

View File

@ -39,7 +39,11 @@ public class ServerConnection {
.addListener(new ChannelFutureListener() { .addListener(new ChannelFutureListener() {
@Override @Override
public void operationComplete(ChannelFuture future) throws Exception { public void operationComplete(ChannelFuture future) throws Exception {
if (future.isSuccess()) {
channel = future.channel(); channel = future.channel();
} else {
proxyPlayer.handleConnectionException(info, future.cause());
}
} }
}); });
} }
@ -49,11 +53,11 @@ public class ServerConnection {
channel = null; channel = null;
} }
public void forward(ByteBuf buf) { public void forward(Object o) {
if (registry != StateRegistry.PLAY) { if (registry != StateRegistry.PLAY) {
throw new IllegalStateException("Not accepting player information until PLAY state"); throw new IllegalStateException("Not accepting player information until PLAY state");
} }
channel.writeAndFlush(buf.retain()); channel.writeAndFlush(o, channel.voidPromise());
} }
private class StateBasedInterceptor extends ChannelInboundHandlerAdapter { private class StateBasedInterceptor extends ChannelInboundHandlerAdapter {
@ -62,7 +66,7 @@ public class ServerConnection {
// Initiate a handshake. // Initiate a handshake.
Handshake handshake = new Handshake(); Handshake handshake = new Handshake();
handshake.setNextStatus(2); // login handshake.setNextStatus(2); // login
handshake.setProtocolVersion(proxyPlayer.getConnection().getProtocolVersion()); // TODO: Expose client version handshake.setProtocolVersion(proxyPlayer.getConnection().getProtocolVersion());
handshake.setServerAddress(info.getAddress().getHostString()); handshake.setServerAddress(info.getAddress().getHostString());
handshake.setPort(info.getAddress().getPort()); handshake.setPort(info.getAddress().getPort());
ctx.writeAndFlush(handshake, ctx.voidPromise()); ctx.writeAndFlush(handshake, ctx.voidPromise());
@ -113,7 +117,7 @@ public class ServerConnection {
if (packet instanceof Disconnect) { if (packet instanceof Disconnect) {
Disconnect disconnect = (Disconnect) packet; Disconnect disconnect = (Disconnect) packet;
ctx.close(); ctx.close();
proxyPlayer.handleConnectionException(disconnect); proxyPlayer.handleConnectionException(info, disconnect);
} }
if (packet instanceof SetCompression) { if (packet instanceof SetCompression) {

View File

@ -1,6 +1,8 @@
package io.minimum.minecraft.velocity.proxy.handler; package io.minimum.minecraft.velocity.proxy.handler;
import io.minimum.minecraft.velocity.protocol.MinecraftPacket; import io.minimum.minecraft.velocity.protocol.MinecraftPacket;
import io.minimum.minecraft.velocity.protocol.packets.Chat;
import io.minimum.minecraft.velocity.protocol.packets.Ping;
import io.minimum.minecraft.velocity.proxy.ConnectedPlayer; import io.minimum.minecraft.velocity.proxy.ConnectedPlayer;
import io.minimum.minecraft.velocity.proxy.MinecraftSessionHandler; import io.minimum.minecraft.velocity.proxy.MinecraftSessionHandler;
import io.minimum.minecraft.velocity.proxy.ServerConnection; import io.minimum.minecraft.velocity.proxy.ServerConnection;
@ -17,11 +19,20 @@ public class PlaySessionHandler implements MinecraftSessionHandler {
@Override @Override
public void handle(MinecraftPacket packet) { public void handle(MinecraftPacket packet) {
if (packet instanceof Ping) {
// Handle the ping.
player.getConnection().write(packet);
return;
}
if (packet instanceof Chat) {
// TODO: handle this ourselves, for now do this
player.getConnectedServer().forward(packet);
}
} }
@Override @Override
public void handleUnknown(ByteBuf buf) { public void handleUnknown(ByteBuf buf) {
connection.forward(buf); connection.forward(buf.retain());
} }
} }