Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding TabCompleteRequestEvent to be triggered when the client sends a tab to the server #1509

Open
wants to merge 2 commits into
base: dev/3.0.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Copyright (C) 2019-2023 Velocity Contributors
*
* The Velocity API is licensed under the terms of the MIT License. For more details,
* reference the LICENSE file in the api top-level directory.
*/

package com.velocitypowered.api.event.player;

import com.velocitypowered.api.event.annotation.AwaitingEvent;
import com.velocitypowered.api.proxy.Player;

import static com.google.common.base.Preconditions.checkNotNull;

/**
* This event is fired after a tab complete request is sent by the player, for clients on
* 1.12.2 and below. You have the opportunity to modify the request sent to the remote server.
*/
@AwaitingEvent
public class TabCompleteRequestEvent {

private final Player player;
private String partialMessage;

/**
* Constructs a new TabCompleteRequestEvent instance.
*
* @param player the player
* @param partialMessage the partial message
*/
public TabCompleteRequestEvent(Player player, String partialMessage) {
this.player = checkNotNull(player, "player");
this.partialMessage = checkNotNull(partialMessage, "partialMessage");
}

/**
* Returns the player requesting the tab completion.
*
* @return the requesting player
*/
public Player getPlayer() {
return player;
}

/**
* Returns the message being partially completed.
*
* @return the partial message
*/
public String getPartialMessage() {
return partialMessage;
}

/**
* Modifies the message being partially completed.
*
*/
public void setPartialMessage(String partialMessage) {
this.partialMessage = partialMessage;
}

@Override
public String toString() {
return "TabCompleteRequestEvent{"
+ "player=" + player
+ ", partialMessage='" + partialMessage + '\''
+ '}';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,7 @@
import com.mojang.brigadier.suggestion.Suggestion;
import com.velocitypowered.api.command.VelocityBrigadierMessage;
import com.velocitypowered.api.event.connection.PluginMessageEvent;
import com.velocitypowered.api.event.player.CookieReceiveEvent;
import com.velocitypowered.api.event.player.PlayerChannelRegisterEvent;
import com.velocitypowered.api.event.player.PlayerClientBrandEvent;
import com.velocitypowered.api.event.player.TabCompleteEvent;
import com.velocitypowered.api.event.player.*;
import com.velocitypowered.api.event.player.configuration.PlayerEnteredConfigurationEvent;
import com.velocitypowered.api.network.ProtocolVersion;
import com.velocitypowered.api.proxy.messages.ChannelIdentifier;
Expand Down Expand Up @@ -712,6 +709,7 @@ private boolean handleRegularTabComplete(TabCompleteRequestPacket packet) {
* @param response the tab complete response from the backend
*/
public void handleTabCompleteResponse(TabCompleteResponsePacket response) {

if (outstandingTabComplete != null && !outstandingTabComplete.isAssumeCommand()) {
if (outstandingTabComplete.getCommand().startsWith("/")) {
this.finishCommandTabComplete(outstandingTabComplete, response);
Expand All @@ -727,38 +725,47 @@ public void handleTabCompleteResponse(TabCompleteResponsePacket response) {

private void finishCommandTabComplete(TabCompleteRequestPacket request,
TabCompleteResponsePacket response) {
String command = request.getCommand().substring(1);
server.getCommandManager().offerBrigadierSuggestions(player, command)
.thenAcceptAsync(offers -> {
boolean legacy =
player.getProtocolVersion().lessThan(ProtocolVersion.MINECRAFT_1_13);
try {
for (Suggestion suggestion : offers.getList()) {
String offer = suggestion.getText();
offer = legacy && !offer.startsWith("/") ? "/" + offer : offer;
if (legacy && offer.startsWith(command)) {
offer = offer.substring(command.length());
}
ComponentHolder tooltip = null;
if (suggestion.getTooltip() != null
&& suggestion.getTooltip() instanceof VelocityBrigadierMessage) {
tooltip = new ComponentHolder(player.getProtocolVersion(),
((VelocityBrigadierMessage) suggestion.getTooltip()).asComponent());
}
response.getOffers().add(new Offer(offer, tooltip));
}
response.getOffers().sort(null);
player.getConnection().write(response);
} catch (Exception e) {
logger.error("Unable to provide tab list completions for {} for command '{}'",
player.getUsername(), command,
e);
}
server.getEventManager().fire(new TabCompleteRequestEvent(player, request.getCommand().substring(1)))
.thenAcceptAsync(e -> {
String command = e.getPartialMessage();
server.getCommandManager().offerBrigadierSuggestions(player, command)
.thenAcceptAsync(offers -> {
boolean legacy =
player.getProtocolVersion().lessThan(ProtocolVersion.MINECRAFT_1_13);
try {
for (Suggestion suggestion : offers.getList()) {
String offer = suggestion.getText();
offer = legacy && !offer.startsWith("/") ? "/" + offer : offer;
if (legacy && offer.startsWith(command)) {
offer = offer.substring(command.length());
}
ComponentHolder tooltip = null;
if (suggestion.getTooltip() != null
&& suggestion.getTooltip() instanceof VelocityBrigadierMessage) {
tooltip = new ComponentHolder(player.getProtocolVersion(),
((VelocityBrigadierMessage) suggestion.getTooltip()).asComponent());
}
response.getOffers().add(new Offer(offer, tooltip));
}
response.getOffers().sort(null);
player.getConnection().write(response);
} catch (Exception ex) {
logger.error("Unable to provide tab list completions for {} for command '{}'",
player.getUsername(), command,
ex);
}
}, player.getConnection().eventLoop()).exceptionally((ex) -> {
logger.error(
"Exception while finishing command tab completion,"
+ " with request {} and response {}",
request, response, ex);
return null;
});
}, player.getConnection().eventLoop()).exceptionally((ex) -> {
logger.error(
"Exception while finishing command tab completion,"
+ " with request {} and response {}",
request, response, ex);
"Exception while finishing regular tab completion,"
+ " with request {} and response{}",
request, response, ex);
return null;
});
}
Expand Down