13
0
geforkt von Mirrors/Velocity

Another round of improvements to tab complete. Fix fallback servers.

Dieser Commit ist enthalten in:
Andrew Steinborn 2019-02-15 16:03:15 -05:00
Ursprung 12f5bdfc48
Commit 02a725035c
4 geänderte Dateien mit 111 neuen und 41 gelöschten Zeilen

Datei anzeigen

@ -57,7 +57,7 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
private final Set<String> knownChannels = new HashSet<>(); private final Set<String> knownChannels = new HashSet<>();
private final Queue<PluginMessage> loginPluginMessages = new ArrayDeque<>(); private final Queue<PluginMessage> loginPluginMessages = new ArrayDeque<>();
private final VelocityServer server; private final VelocityServer server;
private @Nullable TabCompleteRequest outstandingTabComplete; private @Nullable TabCompleteRequest legacyCommandTabComplete;
public ClientPlaySessionHandler(VelocityServer server, ConnectedPlayer player) { public ClientPlaySessionHandler(VelocityServer server, ConnectedPlayer player) {
this.player = player; this.player = player;
@ -143,7 +143,63 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
return false; return false;
} }
// See if this is a proxy command. if (player.getProtocolVersion().compareTo(MINECRAFT_1_13) >= 0) {
return handleTabCompleteModern(packet);
} else {
return handleTabCompleteLegacy(packet);
}
}
private boolean handleTabCompleteModern(TabCompleteRequest packet) {
// In 1.13+, we need to do additional work for the richer suggestions available.
String command = packet.getCommand().substring(1);
int spacePos = command.indexOf(' ');
if (spacePos == -1) {
return false;
}
String commandLabel = command.substring(0, spacePos);
if (!server.getCommandManager().hasCommand(commandLabel)) {
return false;
}
List<String> suggestions = server.getCommandManager().offerSuggestions(player, command);
if (suggestions.isEmpty()) {
return false;
}
List<Offer> offers = new ArrayList<>();
int longestLength = 0;
for (String suggestion : suggestions) {
offers.add(new Offer(suggestion));
if (suggestion.length() > longestLength) {
longestLength = suggestion.length();
}
}
TabCompleteResponse resp = new TabCompleteResponse();
resp.setTransactionId(packet.getTransactionId());
int startPos = packet.getCommand().lastIndexOf(' ') + 1;
int length;
if (startPos == 0) {
startPos = packet.getCommand().length() + 1;
length = longestLength;
} else {
length = packet.getCommand().substring(startPos).indexOf(' ') + 1;
}
resp.setStart(startPos);
resp.setLength(length);
resp.getOffers().addAll(offers);
player.getMinecraftConnection().write(resp);
return true;
}
private boolean handleTabCompleteLegacy(TabCompleteRequest packet) {
// Let us check for a possible proxy command.
String command = packet.getCommand().substring(1); String command = packet.getCommand().substring(1);
int spacePos = command.indexOf(' '); int spacePos = command.indexOf(' ');
if (spacePos >= 0) { if (spacePos >= 0) {
@ -151,18 +207,11 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
if (server.getCommandManager().hasCommand(commandLabel)) { if (server.getCommandManager().hasCommand(commandLabel)) {
List<String> suggestions = server.getCommandManager().offerSuggestions(player, command); List<String> suggestions = server.getCommandManager().offerSuggestions(player, command);
if (!suggestions.isEmpty()) { if (!suggestions.isEmpty()) {
int longestLength = 0;
List<Offer> offers = new ArrayList<>(); List<Offer> offers = new ArrayList<>();
for (String suggestion : suggestions) { for (String suggestion : suggestions) {
offers.add(new Offer(suggestion, null)); offers.add(new Offer(suggestion));
if (suggestion.length() > longestLength) {
longestLength = suggestion.length();
}
} }
TabCompleteResponse resp = new TabCompleteResponse(); TabCompleteResponse resp = new TabCompleteResponse();
resp.setTransactionId(packet.getTransactionId());
resp.setStart(command.lastIndexOf(' ') + 2);
resp.setLength(longestLength);
resp.getOffers().addAll(offers); resp.getOffers().addAll(offers);
player.getMinecraftConnection().write(resp); player.getMinecraftConnection().write(resp);
@ -171,13 +220,10 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
} }
} }
boolean is113 = player.getProtocolVersion().compareTo(MINECRAFT_1_13) >= 0;
if (!is113) {
// Outstanding tab completes are recorded for use with 1.12 clients and below to provide // Outstanding tab completes are recorded for use with 1.12 clients and below to provide
// tab list completion support for command names. In 1.13, Brigadier handles everything for // tab list completion support for command names. In 1.13, Brigadier handles everything for
// us. // us.
outstandingTabComplete = packet; legacyCommandTabComplete = packet;
}
return false; return false;
} }
@ -398,10 +444,8 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
* @param response the tab complete response from the backend * @param response the tab complete response from the backend
*/ */
public void handleTabCompleteResponse(TabCompleteResponse response) { public void handleTabCompleteResponse(TabCompleteResponse response) {
if (outstandingTabComplete != null) { if (legacyCommandTabComplete != null) {
if (!outstandingTabComplete.isAssumeCommand() String command = legacyCommandTabComplete.getCommand().substring(1);
&& outstandingTabComplete.getCommand().startsWith("/")) {
String command = outstandingTabComplete.getCommand().substring(1);
try { try {
List<String> offers = server.getCommandManager().offerSuggestions(player, command); List<String> offers = server.getCommandManager().offerSuggestions(player, command);
for (String offer : offers) { for (String offer : offers) {
@ -413,8 +457,7 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler {
player.getUsername(), player.getUsername(),
command, e); command, e);
} }
outstandingTabComplete = null; legacyCommandTabComplete = null;
}
} }
player.getMinecraftConnection().write(response); player.getMinecraftConnection().write(response);

Datei anzeigen

@ -357,13 +357,13 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
private void handleConnectionException(RegisteredServer rs, @Nullable Component kickReason, private void handleConnectionException(RegisteredServer rs, @Nullable Component kickReason,
Component friendlyReason) { Component friendlyReason) {
if (connectedServer == null) {
// The player isn't yet connected to a server.
Optional<RegisteredServer> nextServer = getNextServerToTry(rs);
if (nextServer.isPresent()) {
// There can't be any connection in flight now. // There can't be any connection in flight now.
connectionInFlight = null; connectionInFlight = null;
if (connectedServer == null) {
// The player isn't yet connected to a server.
Optional<RegisteredServer> nextServer = getNextServerToTry();
if (nextServer.isPresent()) {
createConnectionRequest(nextServer.get()).fireAndForget(); createConnectionRequest(nextServer.get()).fireAndForget();
} else { } else {
disconnect(friendlyReason); disconnect(friendlyReason);
@ -372,7 +372,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
boolean kickedFromCurrent = connectedServer.getServer().equals(rs); boolean kickedFromCurrent = connectedServer.getServer().equals(rs);
ServerKickResult result; ServerKickResult result;
if (kickedFromCurrent) { if (kickedFromCurrent) {
Optional<RegisteredServer> next = getNextServerToTry(); Optional<RegisteredServer> next = getNextServerToTry(rs);
result = next.<ServerKickResult>map(RedirectPlayer::create) result = next.<ServerKickResult>map(RedirectPlayer::create)
.orElseGet(() -> DisconnectPlayer.create(friendlyReason)); .orElseGet(() -> DisconnectPlayer.create(friendlyReason));
} else { } else {
@ -392,6 +392,9 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
DisconnectPlayer res = (DisconnectPlayer) event.getResult(); DisconnectPlayer res = (DisconnectPlayer) event.getResult();
disconnect(res.getReason()); disconnect(res.getReason());
} else if (event.getResult() instanceof RedirectPlayer) { } else if (event.getResult() instanceof RedirectPlayer) {
// There can't be any connection in flight now.
connectionInFlight = null;
RedirectPlayer res = (RedirectPlayer) event.getResult(); RedirectPlayer res = (RedirectPlayer) event.getResult();
createConnectionRequest(res.getServer()) createConnectionRequest(res.getServer())
.connectWithIndication() .connectWithIndication()
@ -419,9 +422,22 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
/** /**
* Finds another server to attempt to log into, if we were unexpectedly disconnected from the * Finds another server to attempt to log into, if we were unexpectedly disconnected from the
* server. * server.
*
* @return the next server to try * @return the next server to try
*/ */
public Optional<RegisteredServer> getNextServerToTry() { public Optional<RegisteredServer> getNextServerToTry() {
return this.getNextServerToTry(null);
}
/**
* Finds another server to attempt to log into, if we were unexpectedly disconnected from the
* server.
*
* @param current the "current" server that the player is on, useful as an override
*
* @return the next server to try
*/
private Optional<RegisteredServer> getNextServerToTry(@Nullable RegisteredServer current) {
if (serversToTry == null) { if (serversToTry == null) {
String virtualHostStr = getVirtualHost().map(InetSocketAddress::getHostString).orElse(""); String virtualHostStr = getVirtualHost().map(InetSocketAddress::getHostString).orElse("");
serversToTry = server.getConfiguration().getForcedHosts().getOrDefault(virtualHostStr, serversToTry = server.getConfiguration().getForcedHosts().getOrDefault(virtualHostStr,
@ -432,17 +448,24 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
serversToTry = server.getConfiguration().getAttemptConnectionOrder(); serversToTry = server.getConfiguration().getAttemptConnectionOrder();
} }
for (; tryIndex < serversToTry.size(); tryIndex++) { for (int i = tryIndex; i < serversToTry.size(); i++) {
String toTryName = serversToTry.get(tryIndex); String toTryName = serversToTry.get(i);
if (connectedServer != null && toTryName.equals(connectedServer.getServerInfo().getName())) { if ((connectedServer != null && hasSameName(connectedServer.getServer(), toTryName))
|| (connectionInFlight != null && hasSameName(connectionInFlight.getServer(), toTryName))
|| (current != null && hasSameName(current, toTryName))) {
continue; continue;
} }
tryIndex = i;
return server.getServer(toTryName); return server.getServer(toTryName);
} }
return Optional.empty(); return Optional.empty();
} }
private static boolean hasSameName(RegisteredServer server, String name) {
return server.getServerInfo().getName().equalsIgnoreCase(name);
}
/** /**
* Sets the player's new connected server and clears the in-flight connection. * Sets the player's new connected server and clears the in-flight connection.
* *

Datei anzeigen

@ -38,7 +38,7 @@ public class TabCompleteRequest implements MinecraftPacket {
this.assumeCommand = assumeCommand; this.assumeCommand = assumeCommand;
} }
public boolean isHasPosition() { public boolean hasPosition() {
return hasPosition; return hasPosition;
} }

Datei anzeigen

@ -112,6 +112,10 @@ public class TabCompleteResponse implements MinecraftPacket {
@Nullable @Nullable
private final Component tooltip; private final Component tooltip;
public Offer(String text) {
this(text, null);
}
public Offer(String text, public Offer(String text,
@Nullable Component tooltip) { @Nullable Component tooltip) {
this.text = text; this.text = text;