Title API (#95)
This commit is contained in:
@@ -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();
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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 {
|
||||
|
@@ -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 +
|
||||
'}';
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user