Mirror von
https://github.com/PaperMC/Velocity.git
synchronisiert 2024-11-16 21:10:30 +01:00
Ursprung
59ca9a534d
Commit
3b6b73f216
@ -64,7 +64,7 @@ dependencies {
|
|||||||
runtimeOnly 'org.jline:jline-terminal-jansi:3.16.0' // Needed for JLine
|
runtimeOnly 'org.jline:jline-terminal-jansi:3.16.0' // Needed for JLine
|
||||||
runtimeOnly 'com.lmax:disruptor:3.4.2' // Async loggers
|
runtimeOnly 'com.lmax:disruptor:3.4.2' // Async loggers
|
||||||
|
|
||||||
implementation 'it.unimi.dsi:fastutil:8.4.1'
|
implementation 'it.unimi.dsi:fastutil-core:8.5.4'
|
||||||
|
|
||||||
implementation(platform("net.kyori:adventure-bom:${adventureVersion}"))
|
implementation(platform("net.kyori:adventure-bom:${adventureVersion}"))
|
||||||
implementation("net.kyori:adventure-nbt")
|
implementation("net.kyori:adventure-nbt")
|
||||||
@ -84,6 +84,7 @@ dependencies {
|
|||||||
|
|
||||||
testImplementation "org.junit.jupiter:junit-jupiter-api:${junitVersion}"
|
testImplementation "org.junit.jupiter:junit-jupiter-api:${junitVersion}"
|
||||||
testImplementation "org.junit.jupiter:junit-jupiter-engine:${junitVersion}"
|
testImplementation "org.junit.jupiter:junit-jupiter-engine:${junitVersion}"
|
||||||
|
testImplementation "org.mockito:mockito-core:3.+"
|
||||||
}
|
}
|
||||||
|
|
||||||
test {
|
test {
|
||||||
@ -91,25 +92,35 @@ test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
shadowJar {
|
shadowJar {
|
||||||
|
// Exclude all the collection types we don't intend to use
|
||||||
exclude 'it/unimi/dsi/fastutil/booleans/**'
|
exclude 'it/unimi/dsi/fastutil/booleans/**'
|
||||||
exclude 'it/unimi/dsi/fastutil/bytes/**'
|
exclude 'it/unimi/dsi/fastutil/bytes/**'
|
||||||
exclude 'it/unimi/dsi/fastutil/chars/**'
|
exclude 'it/unimi/dsi/fastutil/chars/**'
|
||||||
exclude 'it/unimi/dsi/fastutil/doubles/**'
|
exclude 'it/unimi/dsi/fastutil/doubles/**'
|
||||||
exclude 'it/unimi/dsi/fastutil/floats/**'
|
exclude 'it/unimi/dsi/fastutil/floats/**'
|
||||||
|
exclude 'it/unimi/dsi/fastutil/longs/**'
|
||||||
|
exclude 'it/unimi/dsi/fastutil/shorts/**'
|
||||||
|
|
||||||
|
// Exclude the fastutil IO utilities - we don't use them.
|
||||||
|
exclude 'it/unimi/dsi/fastutil/io/**'
|
||||||
|
|
||||||
|
// Exclude most of the int types - Object2IntMap have a values() method that returns an IntCollection
|
||||||
exclude 'it/unimi/dsi/fastutil/ints/*Int2*'
|
exclude 'it/unimi/dsi/fastutil/ints/*Int2*'
|
||||||
exclude 'it/unimi/dsi/fastutil/ints/IntAVL*'
|
exclude 'it/unimi/dsi/fastutil/ints/IntAVL*'
|
||||||
exclude 'it/unimi/dsi/fastutil/ints/IntArray*'
|
exclude 'it/unimi/dsi/fastutil/ints/IntArray*'
|
||||||
exclude 'it/unimi/dsi/fastutil/ints/IntBi*'
|
exclude 'it/unimi/dsi/fastutil/ints/*IntBi*'
|
||||||
|
exclude 'it/unimi/dsi/fastutil/ints/Int*Pair'
|
||||||
exclude 'it/unimi/dsi/fastutil/ints/IntLinked*'
|
exclude 'it/unimi/dsi/fastutil/ints/IntLinked*'
|
||||||
exclude 'it/unimi/dsi/fastutil/ints/IntList*'
|
exclude 'it/unimi/dsi/fastutil/ints/IntList*'
|
||||||
|
exclude 'it/unimi/dsi/fastutil/ints/IntHeap*'
|
||||||
exclude 'it/unimi/dsi/fastutil/ints/IntOpen*'
|
exclude 'it/unimi/dsi/fastutil/ints/IntOpen*'
|
||||||
exclude 'it/unimi/dsi/fastutil/ints/IntRB*'
|
exclude 'it/unimi/dsi/fastutil/ints/IntRB*'
|
||||||
exclude 'it/unimi/dsi/fastutil/ints/IntSet*'
|
exclude 'it/unimi/dsi/fastutil/ints/IntSet*'
|
||||||
exclude 'it/unimi/dsi/fastutil/ints/IntSorted*'
|
exclude 'it/unimi/dsi/fastutil/ints/IntSorted*'
|
||||||
exclude 'it/unimi/dsi/fastutil/ints/*Priority*'
|
exclude 'it/unimi/dsi/fastutil/ints/*Priority*'
|
||||||
exclude 'it/unimi/dsi/fastutil/ints/*BigList*'
|
exclude 'it/unimi/dsi/fastutil/ints/*BigList*'
|
||||||
exclude 'it/unimi/dsi/fastutil/io/**'
|
|
||||||
exclude 'it/unimi/dsi/fastutil/longs/**'
|
// Try to exclude everything BUT Object2Int{LinkedOpen,Open,CustomOpen}HashMap
|
||||||
exclude 'it/unimi/dsi/fastutil/objects/*ObjectArray*'
|
exclude 'it/unimi/dsi/fastutil/objects/*ObjectArray*'
|
||||||
exclude 'it/unimi/dsi/fastutil/objects/*ObjectAVL*'
|
exclude 'it/unimi/dsi/fastutil/objects/*ObjectAVL*'
|
||||||
exclude 'it/unimi/dsi/fastutil/objects/*Object*Big*'
|
exclude 'it/unimi/dsi/fastutil/objects/*Object*Big*'
|
||||||
@ -127,7 +138,8 @@ shadowJar {
|
|||||||
exclude 'it/unimi/dsi/fastutil/objects/*Object2Short*'
|
exclude 'it/unimi/dsi/fastutil/objects/*Object2Short*'
|
||||||
exclude 'it/unimi/dsi/fastutil/objects/*ObjectRB*'
|
exclude 'it/unimi/dsi/fastutil/objects/*ObjectRB*'
|
||||||
exclude 'it/unimi/dsi/fastutil/objects/*Reference*'
|
exclude 'it/unimi/dsi/fastutil/objects/*Reference*'
|
||||||
exclude 'it/unimi/dsi/fastutil/shorts/**'
|
|
||||||
|
// Exclude Checker Framework annotations
|
||||||
exclude 'org/checkerframework/checker/**'
|
exclude 'org/checkerframework/checker/**'
|
||||||
|
|
||||||
relocate 'org.bstats', 'com.velocitypowered.proxy.bstats'
|
relocate 'org.bstats', 'com.velocitypowered.proxy.bstats'
|
||||||
|
@ -247,6 +247,8 @@ public class VelocityServer implements ProxyServer, ForwardingAudience {
|
|||||||
LogManager.shutdown();
|
LogManager.shutdown();
|
||||||
System.exit(1);
|
System.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
commandManager.setAnnounceProxyCommands(configuration.isAnnounceProxyCommands());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.error("Unable to read/load/save your velocity.toml. The server will shut down.", e);
|
logger.error("Unable to read/load/save your velocity.toml. The server will shut down.", e);
|
||||||
LogManager.shutdown();
|
LogManager.shutdown();
|
||||||
@ -384,6 +386,7 @@ public class VelocityServer implements ProxyServer, ForwardingAudience {
|
|||||||
newConfiguration.getQueryPort());
|
newConfiguration.getQueryPort());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
commandManager.setAnnounceProxyCommands(newConfiguration.isAnnounceProxyCommands());
|
||||||
ipAttemptLimiter = Ratelimiters.createWithMilliseconds(newConfiguration.getLoginRatelimit());
|
ipAttemptLimiter = Ratelimiters.createWithMilliseconds(newConfiguration.getLoginRatelimit());
|
||||||
this.configuration = newConfiguration;
|
this.configuration = newConfiguration;
|
||||||
eventManager.fireAndForget(new ProxyReloadEvent());
|
eventManager.fireAndForget(new ProxyReloadEvent());
|
||||||
|
@ -33,6 +33,7 @@ import com.spotify.futures.CompletableFutures;
|
|||||||
import com.velocitypowered.api.command.Command;
|
import com.velocitypowered.api.command.Command;
|
||||||
import com.velocitypowered.api.command.CommandMeta;
|
import com.velocitypowered.api.command.CommandMeta;
|
||||||
import com.velocitypowered.api.command.CommandSource;
|
import com.velocitypowered.api.command.CommandSource;
|
||||||
|
import com.velocitypowered.api.proxy.Player;
|
||||||
import com.velocitypowered.proxy.command.brigadier.VelocityArgumentCommandNode;
|
import com.velocitypowered.proxy.command.brigadier.VelocityArgumentCommandNode;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@ -62,10 +63,12 @@ final class SuggestionsProvider<S> {
|
|||||||
|
|
||||||
private final @GuardedBy("lock") CommandDispatcher<S> dispatcher;
|
private final @GuardedBy("lock") CommandDispatcher<S> dispatcher;
|
||||||
private final Lock lock;
|
private final Lock lock;
|
||||||
|
private boolean announceProxyCommands;
|
||||||
|
|
||||||
SuggestionsProvider(final CommandDispatcher<S> dispatcher, final Lock lock) {
|
SuggestionsProvider(final CommandDispatcher<S> dispatcher, final Lock lock) {
|
||||||
this.dispatcher = Preconditions.checkNotNull(dispatcher, "dispatcher");
|
this.dispatcher = Preconditions.checkNotNull(dispatcher, "dispatcher");
|
||||||
this.lock = Preconditions.checkNotNull(lock, "lock");
|
this.lock = Preconditions.checkNotNull(lock, "lock");
|
||||||
|
this.announceProxyCommands = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -149,6 +152,10 @@ final class SuggestionsProvider<S> {
|
|||||||
// TODO Is this actually faster? It may incur an allocation
|
// TODO Is this actually faster? It may incur an allocation
|
||||||
final String input = reader.getRead().toLowerCase(Locale.ENGLISH);
|
final String input = reader.getRead().toLowerCase(Locale.ENGLISH);
|
||||||
|
|
||||||
|
if (source instanceof Player && !this.announceProxyCommands) {
|
||||||
|
return new SuggestionsBuilder(input, 0).buildFuture();
|
||||||
|
}
|
||||||
|
|
||||||
final Collection<CommandNode<S>> aliases = contextSoFar.getRootNode().getChildren();
|
final Collection<CommandNode<S>> aliases = contextSoFar.getRootNode().getChildren();
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
final CompletableFuture<Suggestions>[] futures = new CompletableFuture[aliases.size()];
|
final CompletableFuture<Suggestions>[] futures = new CompletableFuture[aliases.size()];
|
||||||
@ -368,4 +375,13 @@ final class SuggestionsProvider<S> {
|
|||||||
return Suggestions.merge(fullInput, suggestions);
|
return Suggestions.merge(fullInput, suggestions);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a flag indicating whether or not alias suggestions shall be returned to the user.
|
||||||
|
*
|
||||||
|
* @param announceProxyCommands whether alias suggestions can be returned
|
||||||
|
*/
|
||||||
|
public void setAnnounceProxyCommands(boolean announceProxyCommands) {
|
||||||
|
this.announceProxyCommands = announceProxyCommands;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,6 +77,10 @@ public class VelocityCommandManager implements CommandManager {
|
|||||||
this.injector = new CommandGraphInjector<>(this.dispatcher, this.lock.readLock());
|
this.injector = new CommandGraphInjector<>(this.dispatcher, this.lock.readLock());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setAnnounceProxyCommands(boolean announceProxyCommands) {
|
||||||
|
this.suggestionsProvider.setAnnounceProxyCommands(announceProxyCommands);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommandMeta.Builder metaBuilder(final String alias) {
|
public CommandMeta.Builder metaBuilder(final String alias) {
|
||||||
Preconditions.checkNotNull(alias, "alias");
|
Preconditions.checkNotNull(alias, "alias");
|
||||||
|
@ -43,7 +43,6 @@ import com.velocitypowered.proxy.protocol.packet.brigadier.ArgumentPropertyRegis
|
|||||||
import com.velocitypowered.proxy.util.collect.IdentityHashStrategy;
|
import com.velocitypowered.proxy.util.collect.IdentityHashStrategy;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import it.unimi.dsi.fastutil.objects.Object2IntLinkedOpenCustomHashMap;
|
import it.unimi.dsi.fastutil.objects.Object2IntLinkedOpenCustomHashMap;
|
||||||
import it.unimi.dsi.fastutil.objects.Object2IntLinkedOpenHashMap;
|
|
||||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||||
import java.util.ArrayDeque;
|
import java.util.ArrayDeque;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -20,8 +20,13 @@ package com.velocitypowered.proxy.command;
|
|||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import com.velocitypowered.api.command.CommandSource;
|
import com.velocitypowered.api.command.CommandSource;
|
||||||
|
import com.velocitypowered.api.permission.Tristate;
|
||||||
|
import com.velocitypowered.api.proxy.Player;
|
||||||
import com.velocitypowered.proxy.event.MockEventManager;
|
import com.velocitypowered.proxy.event.MockEventManager;
|
||||||
import com.velocitypowered.proxy.event.VelocityEventManager;
|
import com.velocitypowered.proxy.event.VelocityEventManager;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@ -68,4 +73,11 @@ abstract class CommandTestSuite {
|
|||||||
final var actual = manager.offerSuggestions(source, input).join();
|
final var actual = manager.offerSuggestions(source, input).join();
|
||||||
assertEquals(Arrays.asList(expectedSuggestions), actual);
|
assertEquals(Arrays.asList(expectedSuggestions), actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final void assertPlayerSuggestions(final String input, final String... expectedSuggestions) {
|
||||||
|
final var player = mock(Player.class);
|
||||||
|
when(player.getPermissionValue(any())).thenReturn(Tristate.UNDEFINED);
|
||||||
|
final var actual = manager.offerSuggestions(player, input).join();
|
||||||
|
assertEquals(Arrays.asList(expectedSuggestions), actual);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,17 @@ public class SuggestionsProviderTests extends CommandTestSuite {
|
|||||||
assertSuggestions("", "bar", "baz", "foo"); // in alphabetical order
|
assertSuggestions("", "bar", "baz", "foo"); // in alphabetical order
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void willNotSuggestAliasesIfNotAnnouncingForPlayer() {
|
||||||
|
manager.setAnnounceProxyCommands(false);
|
||||||
|
manager.register(manager.metaBuilder("foo").build(), NoSuggestionsCommand.INSTANCE);
|
||||||
|
manager.register(manager.metaBuilder("bar").build(), NoSuggestionsCommand.INSTANCE);
|
||||||
|
manager.register(manager.metaBuilder("baz").build(), NoSuggestionsCommand.INSTANCE);
|
||||||
|
|
||||||
|
assertPlayerSuggestions(""); // for a fake player
|
||||||
|
assertSuggestions("", "bar", "baz", "foo"); // for non-players
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testDoesNotSuggestForLeadingWhitespace() {
|
void testDoesNotSuggestForLeadingWhitespace() {
|
||||||
final var meta = manager.metaBuilder("hello").build();
|
final var meta = manager.metaBuilder("hello").build();
|
||||||
@ -210,6 +221,24 @@ public class SuggestionsProviderTests extends CommandTestSuite {
|
|||||||
assertSuggestions("hello ", "suggestion");
|
assertSuggestions("hello ", "suggestion");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Hints and argument suggestions should still be sent even when aliases are not being suggested.
|
||||||
|
@Test
|
||||||
|
void testSuggestWillSuggestArgumentsEvenWhenAliasesAreNot() {
|
||||||
|
final var hint = RequiredArgumentBuilder
|
||||||
|
.<CommandSource, String>argument("hint", word())
|
||||||
|
.suggests((context, builder) -> builder.suggest("suggestion").buildFuture())
|
||||||
|
.build();
|
||||||
|
final var meta = manager.metaBuilder("hello")
|
||||||
|
.hint(hint)
|
||||||
|
.build();
|
||||||
|
manager.setAnnounceProxyCommands(false);
|
||||||
|
manager.register(meta, NoSuggestionsCommand.INSTANCE);
|
||||||
|
|
||||||
|
assertSuggestions("hello ", "suggestion");
|
||||||
|
assertPlayerSuggestions("hello ", "suggestion");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testDoesNotSuggestHintIfHintSuggestionProviderFutureCompletesExceptionally() {
|
void testDoesNotSuggestHintIfHintSuggestionProviderFutureCompletesExceptionally() {
|
||||||
final var hint = RequiredArgumentBuilder
|
final var hint = RequiredArgumentBuilder
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren