Title API (#95)

This commit is contained in:
Andrew Steinborn
2018-09-21 15:58:47 -04:00
committed by GitHub
parent 1e04d27bb7
commit ee917682e0
9 changed files with 510 additions and 5 deletions

View File

@@ -219,6 +219,9 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
player.getConnectedServer().getMinecraftConnection().delayedWrite(pm);
}
// Clear any title from the previous server.
player.getConnection().delayedWrite(TitlePacket.resetForProtocolVersion(player.getProtocolVersion()));
// Flush everything
player.getConnection().flush();
player.getConnectedServer().getMinecraftConnection().flush();

View File

@@ -15,6 +15,9 @@ import com.velocitypowered.api.proxy.player.PlayerSettings;
import com.velocitypowered.api.proxy.server.RegisteredServer;
import com.velocitypowered.api.util.GameProfile;
import com.velocitypowered.api.util.MessagePosition;
import com.velocitypowered.api.util.title.TextTitle;
import com.velocitypowered.api.util.title.Title;
import com.velocitypowered.api.util.title.Titles;
import com.velocitypowered.proxy.VelocityServer;
import com.velocitypowered.proxy.connection.MinecraftConnection;
import com.velocitypowered.proxy.connection.MinecraftConnectionAssociation;
@@ -22,6 +25,7 @@ import com.velocitypowered.proxy.connection.VelocityConstants;
import com.velocitypowered.proxy.connection.backend.VelocityServerConnection;
import com.velocitypowered.proxy.connection.util.ConnectionMessages;
import com.velocitypowered.proxy.connection.util.ConnectionRequestResults;
import com.velocitypowered.proxy.protocol.ProtocolConstants;
import com.velocitypowered.proxy.protocol.packet.*;
import com.velocitypowered.proxy.server.VelocityRegisteredServer;
import com.velocitypowered.proxy.util.ThrowableUtils;
@@ -139,11 +143,20 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
byte pos = (byte) position.ordinal();
String json;
if (position == MessagePosition.ACTION_BAR) {
// Due to issues with action bar packets, we'll need to convert the text message into a legacy message
// and then inject the legacy text into a component... yuck!
JsonObject object = new JsonObject();
object.addProperty("text", ComponentSerializers.LEGACY.serialize(component));
json = VelocityServer.GSON.toJson(object);
if (getProtocolVersion() >= ProtocolConstants.MINECRAFT_1_11) {
// We can use the title packet instead.
TitlePacket pkt = new TitlePacket();
pkt.setAction(TitlePacket.SET_ACTION_BAR);
pkt.setComponent(ComponentSerializers.JSON.serialize(component));
connection.write(pkt);
return;
} else {
// Due to issues with action bar packets, we'll need to convert the text message into a legacy message
// and then inject the legacy text into a component... yuck!
JsonObject object = new JsonObject();
object.addProperty("text", ComponentSerializers.LEGACY.serialize(component));
json = VelocityServer.GSON.toJson(object);
}
} else {
json = ComponentSerializers.JSON.serialize(component);
}
@@ -176,6 +189,48 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
connection.closeWith(Disconnect.create(reason));
}
@Override
public void sendTitle(Title title) {
Preconditions.checkNotNull(title, "title");
if (title.equals(Titles.reset())) {
connection.write(TitlePacket.resetForProtocolVersion(connection.getProtocolVersion()));
} else if (title.equals(Titles.hide())) {
connection.write(TitlePacket.hideForProtocolVersion(connection.getProtocolVersion()));
} else if (title instanceof TextTitle) {
TextTitle tt = (TextTitle) title;
if (tt.isResetBeforeSend()) {
connection.delayedWrite(TitlePacket.resetForProtocolVersion(connection.getProtocolVersion()));
}
if (tt.getTitle().isPresent()) {
TitlePacket titlePkt = new TitlePacket();
titlePkt.setAction(TitlePacket.SET_TITLE);
titlePkt.setComponent(ComponentSerializers.JSON.serialize(tt.getTitle().get()));
connection.delayedWrite(titlePkt);
}
if (tt.getSubtitle().isPresent()) {
TitlePacket titlePkt = new TitlePacket();
titlePkt.setAction(TitlePacket.SET_SUBTITLE);
titlePkt.setComponent(ComponentSerializers.JSON.serialize(tt.getSubtitle().get()));
connection.delayedWrite(titlePkt);
}
if (tt.areTimesSet()) {
TitlePacket timesPkt = TitlePacket.timesForProtocolVersion(connection.getProtocolVersion());
timesPkt.setFadeIn(tt.getFadeIn());
timesPkt.setStay(tt.getStay());
timesPkt.setFadeOut(tt.getFadeOut());
connection.delayedWrite(timesPkt);
}
connection.flush();
} else {
throw new IllegalArgumentException("Unknown title class " + title.getClass().getName());
}
}
public VelocityServerConnection getConnectedServer() {
return connectedServer;
}

View File

@@ -136,6 +136,12 @@ public enum StateRegistry {
map(0x44, MINECRAFT_1_12, true),
map(0x45, MINECRAFT_1_12_1, true),
map(0x48, MINECRAFT_1_13, true));
CLIENTBOUND.register(TitlePacket.class, TitlePacket::new,
map(0x45, MINECRAFT_1_8, true),
map(0x45, MINECRAFT_1_9, true),
map(0x47, MINECRAFT_1_12, true),
map(0x48, MINECRAFT_1_12_1, true),
map(0x4B, MINECRAFT_1_13, true));
}
},
LOGIN {

View File

@@ -0,0 +1,137 @@
package com.velocitypowered.proxy.protocol.packet;
import com.google.common.base.Preconditions;
import com.velocitypowered.proxy.protocol.MinecraftPacket;
import com.velocitypowered.proxy.protocol.ProtocolConstants;
import com.velocitypowered.proxy.protocol.ProtocolUtils;
import io.netty.buffer.ByteBuf;
public class TitlePacket implements MinecraftPacket {
public static final int SET_TITLE = 0;
public static final int SET_SUBTITLE = 1;
public static final int SET_ACTION_BAR = 2;
public static final int SET_TIMES = 3;
public static final int SET_TIMES_OLD = 2;
public static final int HIDE = 4;
public static final int HIDE_OLD = 3;
public static final int RESET = 5;
public static final int RESET_OLD = 4;
private int action;
private String component;
private int fadeIn;
private int stay;
private int fadeOut;
@Override
public void decode(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) {
throw new UnsupportedOperationException(); // encode only
}
@Override
public void encode(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) {
ProtocolUtils.writeVarInt(buf, action);
if (protocolVersion >= ProtocolConstants.MINECRAFT_1_11) {
// 1.11+ shifted the action enum by 1 to handle the action bar
switch (action) {
case SET_TITLE:
case SET_SUBTITLE:
case SET_ACTION_BAR:
ProtocolUtils.writeString(buf, component);
break;
case SET_TIMES:
buf.writeInt(fadeIn);
buf.writeInt(stay);
buf.writeInt(fadeOut);
break;
case HIDE:
case RESET:
break;
}
} else {
switch (action) {
case SET_TITLE:
case SET_SUBTITLE:
ProtocolUtils.writeString(buf, component);
break;
case SET_TIMES_OLD:
buf.writeInt(fadeIn);
buf.writeInt(stay);
buf.writeInt(fadeOut);
break;
case HIDE_OLD:
case RESET_OLD:
break;
}
}
}
public int getAction() {
return action;
}
public void setAction(int action) {
this.action = action;
}
public String getComponent() {
return component;
}
public void setComponent(String component) {
this.component = component;
}
public int getFadeIn() {
return fadeIn;
}
public void setFadeIn(int fadeIn) {
this.fadeIn = fadeIn;
}
public int getStay() {
return stay;
}
public void setStay(int stay) {
this.stay = stay;
}
public int getFadeOut() {
return fadeOut;
}
public void setFadeOut(int fadeOut) {
this.fadeOut = fadeOut;
}
public static TitlePacket hideForProtocolVersion(int protocolVersion) {
TitlePacket packet = new TitlePacket();
packet.setAction(protocolVersion >= ProtocolConstants.MINECRAFT_1_11 ? TitlePacket.HIDE : TitlePacket.HIDE_OLD);
return packet;
}
public static TitlePacket resetForProtocolVersion(int protocolVersion) {
TitlePacket packet = new TitlePacket();
packet.setAction(protocolVersion >= ProtocolConstants.MINECRAFT_1_11 ? TitlePacket.RESET : TitlePacket.RESET_OLD);
return packet;
}
public static TitlePacket timesForProtocolVersion(int protocolVersion) {
TitlePacket packet = new TitlePacket();
packet.setAction(protocolVersion >= ProtocolConstants.MINECRAFT_1_11 ? TitlePacket.SET_TIMES : TitlePacket.SET_TIMES_OLD);
return packet;
}
@Override
public String toString() {
return "TitlePacket{" +
"action=" + action +
", component='" + component + '\'' +
", fadeIn=" + fadeIn +
", stay=" + stay +
", fadeOut=" + fadeOut +
'}';
}
}