Skip to content
This repository was archived by the owner on Apr 28, 2025. It is now read-only.

Commit 96ae6b9

Browse files
Merge branch 'GemstoneGG:libdeflate' into libdeflate
2 parents 08f82fc + 58ec321 commit 96ae6b9

48 files changed

Lines changed: 717 additions & 234 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

api/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ tasks {
6161
o.encoding = "UTF-8"
6262
o.source = "17"
6363

64+
o.use()
6465
o.links(
6566
"https://www.slf4j.org/apidocs/",
6667
"https://guava.dev/releases/${libs.guava.get().version}/api/docs/",

api/src/main/java/com/velocitypowered/api/proxy/config/ProxyConfig.java

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,4 +155,59 @@ public interface ProxyConfig {
155155
* @return read timeout (in milliseconds)
156156
*/
157157
int getReadTimeout();
158+
159+
/**
160+
* Get the rate limit for how fast a player can execute commands.
161+
*
162+
* @return the command rate limit (in milliseconds)
163+
*/
164+
int getCommandRatelimit();
165+
166+
/**
167+
* Get whether we should forward commands to the backend if the player is rate limited.
168+
*
169+
* @return whether to forward commands if rate limited
170+
*/
171+
boolean isForwardCommandsIfRateLimited();
172+
173+
/**
174+
* Get the kick limit for commands that are rate limited.
175+
* If this limit is 0 or less, the player will not be kicked.
176+
*
177+
* @return the rate-limited command rate limit
178+
*/
179+
int getKickAfterRateLimitedCommands();
180+
181+
/**
182+
* Get whether the proxy should kick players who are command rate-limited.
183+
*
184+
* @return whether to kick players who are rate limited
185+
*/
186+
default boolean isKickOnCommandRateLimit() {
187+
return getKickAfterRateLimitedCommands() > 0;
188+
}
189+
190+
/**
191+
* Get the rate limit for how fast a player can tab complete.
192+
*
193+
* @return the tab complete rate limit (in milliseconds)
194+
*/
195+
int getTabCompleteRatelimit();
196+
197+
/**
198+
* Get the kick limit for tab completes that are rate limited.
199+
* If this limit is 0 or less, the player will not be kicked.
200+
*
201+
* @return the rate-limited command rate limit
202+
*/
203+
int getKickAfterRateLimitedTabCompletes();
204+
205+
/**
206+
* Get whether the proxy should kick players who are tab complete rate limited.
207+
*
208+
* @return whether to kick players who are rate limited
209+
*/
210+
default boolean isKickOnTabCompleteRateLimit() {
211+
return getKickAfterRateLimitedTabCompletes() > 0;
212+
}
158213
}

api/src/main/java/com/velocitypowered/api/proxy/player/TabList.java

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,15 @@ public interface TabList {
4040
* Adds a {@link TabListEntry} to the {@link Player}'s tab list.
4141
*
4242
* @param entry to add to the tab list
43+
* @throws IllegalArgumentException on versions below 1.19.3, if an entry with the same UUID already exists
4344
*/
4445
void addEntry(TabListEntry entry);
4546

4647
/**
4748
* Adds a {@link Iterable} of {@link TabListEntry}'s to the {@link Player}'s tab list.
4849
*
4950
* @param entries to add to the tab list
51+
* @throws IllegalArgumentException on versions below 1.19.3, if an entry with the same UUID already exists
5052
*/
5153
default void addEntries(Iterable<TabListEntry> entries) {
5254
for (TabListEntry entry : entries) {
@@ -58,6 +60,7 @@ default void addEntries(Iterable<TabListEntry> entries) {
5860
* Adds an array of {@link TabListEntry}'s to the {@link Player}'s tab list.
5961
*
6062
* @param entries to add to the tab list
63+
* @throws IllegalArgumentException on versions below 1.19.3, if an entry with the same UUID already exists
6164
*/
6265
default void addEntries(TabListEntry... entries) {
6366
for (TabListEntry entry : entries) {
@@ -187,6 +190,26 @@ default TabListEntry buildEntry(GameProfile profile, @Nullable Component display
187190
* @deprecated Internal usage. Use {@link TabListEntry.Builder} instead.
188191
*/
189192
@Deprecated
193+
default TabListEntry buildEntry(GameProfile profile, @Nullable Component displayName, int latency,
194+
int gameMode, @Nullable ChatSession chatSession, boolean listed, int listOrder) {
195+
return buildEntry(profile, displayName, latency, gameMode, chatSession, listed, listOrder, true);
196+
}
197+
198+
/**
199+
* Represents an entry in a {@link Player}'s tab list.
200+
*
201+
* @param profile the profile
202+
* @param displayName the display name
203+
* @param latency the latency
204+
* @param gameMode the game mode
205+
* @param chatSession the chat session
206+
* @param listed the visible status of entry
207+
* @param listOrder the order/priority of entry in the tab list
208+
* @param showHat the visibility of this entry's hat layer
209+
* @return the entry
210+
* @deprecated Internal usage. Use {@link TabListEntry.Builder} instead.
211+
*/
212+
@Deprecated
190213
TabListEntry buildEntry(GameProfile profile, @Nullable Component displayName, int latency,
191-
int gameMode, @Nullable ChatSession chatSession, boolean listed, int listOrder);
214+
int gameMode, @Nullable ChatSession chatSession, boolean listed, int listOrder, boolean showHat);
192215
}

api/src/main/java/com/velocitypowered/api/proxy/player/TabListEntry.java

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,27 @@ default TabListEntry setListOrder(int order) {
160160
return this;
161161
}
162162

163+
/**
164+
* Returns whether this entry's hat layer is shown in the tab list.
165+
*
166+
* @return whether to show this entry's hat layer
167+
* @since Minecraft 1.21.4
168+
*/
169+
default boolean isShowHat() {
170+
return true;
171+
}
172+
173+
/**
174+
* Sets whether to show this entry's hat layer in the tab list.
175+
*
176+
* @param showHat whether to show this entry's hat layer
177+
* @return {@code this}, for chaining
178+
* @since Minecraft 1.21.4
179+
*/
180+
default TabListEntry setShowHat(boolean showHat) {
181+
return this;
182+
}
183+
163184
/**
164185
* Returns a {@link Builder} to create a {@link TabListEntry}.
165186
*
@@ -183,6 +204,7 @@ final class Builder {
183204
private int gameMode = 0;
184205
private boolean listed = true;
185206
private int listOrder = 0;
207+
private boolean showHat;
186208

187209
private @Nullable ChatSession chatSession;
188210

@@ -271,7 +293,7 @@ public Builder gameMode(final int gameMode) {
271293
* Sets whether this entry should be visible.
272294
*
273295
* @param listed to set
274-
* @return ${code this}, for chaining
296+
* @return {@code this}, for chaining
275297
* @see TabListEntry#isListed()
276298
*/
277299
public Builder listed(final boolean listed) {
@@ -283,7 +305,7 @@ public Builder listed(final boolean listed) {
283305
* Sets the order/priority of this entry in the tab list.
284306
*
285307
* @param order to set
286-
* @return ${code this}, for chaining
308+
* @return {@code this}, for chaining
287309
* @since Minecraft 1.21.2
288310
* @see TabListEntry#getListOrder()
289311
*/
@@ -292,6 +314,18 @@ public Builder listOrder(final int order) {
292314
return this;
293315
}
294316

317+
/**
318+
* Sets whether this entry's hat layer should be shown in the tab list.
319+
*
320+
* @param showHat to set
321+
* @return {@code this}, for chaining
322+
* @see TabListEntry#isShowHat()
323+
*/
324+
public Builder showHat(final boolean showHat) {
325+
this.showHat = showHat;
326+
return this;
327+
}
328+
295329
/**
296330
* Constructs the {@link TabListEntry} specified by {@code this} {@link Builder}.
297331
*
@@ -304,7 +338,7 @@ public TabListEntry build() {
304338
if (profile == null) {
305339
throw new IllegalStateException("The GameProfile must be set when building a TabListEntry");
306340
}
307-
return tabList.buildEntry(profile, displayName, latency, gameMode, chatSession, listed, listOrder);
341+
return tabList.buildEntry(profile, displayName, latency, gameMode, chatSession, listed, listOrder, showHat);
308342
}
309343
}
310344
}

gradle/libs.versions.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ jopt = "net.sf.jopt-simple:jopt-simple:5.0.4"
3939
junit = "org.junit.jupiter:junit-jupiter:5.11.4"
4040
jspecify = "org.jspecify:jspecify:1.0.0"
4141
kyori-ansi = "net.kyori:ansi:1.1.1"
42-
guava = "com.google.guava:guava:33.4.0-jre"
42+
guava = "com.google.guava:guava:33.4.5-jre"
4343
gson = "com.google.code.gson:gson:2.12.1"
4444
guice = "com.google.inject:guice:6.0.0"
4545
lmbda = "org.lanternpowered:lmbda:2.0.0"
@@ -48,7 +48,7 @@ log4j-core = { module = "org.apache.logging.log4j:log4j-core", version.ref = "lo
4848
log4j-slf4j-impl = { module = "org.apache.logging.log4j:log4j-slf4j2-impl", version.ref = "log4j" }
4949
log4j-iostreams = { module = "org.apache.logging.log4j:log4j-iostreams", version.ref = "log4j" }
5050
log4j-jul = { module = "org.apache.logging.log4j:log4j-jul", version.ref = "log4j" }
51-
mockito = "org.mockito:mockito-core:5.16.0"
51+
mockito = "org.mockito:mockito-core:5.16.1"
5252
netty-codec = { module = "io.netty:netty-codec", version.ref = "netty" }
5353
netty-codec-haproxy = { module = "io.netty:netty-codec-haproxy", version.ref = "netty" }
5454
netty-codec-http = { module = "io.netty:netty-codec-http", version.ref = "netty" }
@@ -58,7 +58,7 @@ netty-transport-native-kqueue = { module = "io.netty:netty-transport-native-kque
5858
nightconfig = "com.electronwill.night-config:toml:3.8.1"
5959
slf4j = "org.slf4j:slf4j-api:2.0.17"
6060
snakeyaml = "org.yaml:snakeyaml:1.33"
61-
spotbugs-annotations = "com.github.spotbugs:spotbugs-annotations:4.9.2"
61+
spotbugs-annotations = "com.github.spotbugs:spotbugs-annotations:4.9.3"
6262
terminalconsoleappender = "net.minecrell:terminalconsoleappender:1.3.0"
6363

6464
[bundles]

proxy/src/main/java/com/velocitypowered/proxy/VelocityServer.java

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@
9595
import java.io.BufferedReader;
9696
import java.io.IOException;
9797
import java.io.InputStream;
98+
import java.net.InetAddress;
9899
import java.net.InetSocketAddress;
99100
import java.net.http.HttpClient;
100101
import java.nio.charset.StandardCharsets;
@@ -190,7 +191,9 @@ public class VelocityServer implements ProxyServer, ForwardingAudience {
190191
private final Map<UUID, ConnectedPlayer> connectionsByUuid = new ConcurrentHashMap<>();
191192
private final Map<String, ConnectedPlayer> connectionsByName = new ConcurrentHashMap<>();
192193
private final VelocityConsole console;
193-
private @MonotonicNonNull Ratelimiter ipAttemptLimiter;
194+
private @MonotonicNonNull Ratelimiter<InetAddress> ipAttemptLimiter;
195+
private @MonotonicNonNull Ratelimiter<UUID> commandRateLimiter;
196+
private @MonotonicNonNull Ratelimiter<UUID> tabCompleteRateLimiter;
194197
private final VelocityEventManager eventManager;
195198
private final VelocityScheduler scheduler;
196199
private final VelocityChannelRegistrar channelRegistrar = new VelocityChannelRegistrar();
@@ -359,6 +362,8 @@ void start() {
359362
registerTranslations(true);
360363

361364
ipAttemptLimiter = Ratelimiters.createWithMilliseconds(configuration.getLoginRatelimit());
365+
commandRateLimiter = Ratelimiters.createWithMilliseconds(configuration.getCommandRatelimit());
366+
tabCompleteRateLimiter = Ratelimiters.createWithMilliseconds(configuration.getTabCompleteRatelimit());
362367
loadPlugins();
363368

364369
// Go ahead and fire the proxy initialization event. We block since plugins should have a chance
@@ -616,7 +621,7 @@ public boolean reloadConfiguration() throws IOException {
616621
Optional<RegisteredServer> next = player.getNextServerToTry();
617622
if (next.isPresent()) {
618623
player.createConnectionRequest(next.get()).connectWithIndication()
619-
.whenCompleteAsync((success, ex) -> {
624+
.whenComplete((success, ex) -> {
620625
if (ex != null || success == null || !success) {
621626
player.disconnect(Component.text("Your server has been changed, but we could "
622627
+ "not move you to any fallback servers."));
@@ -987,10 +992,18 @@ public HttpClient createHttpClient() {
987992
return cm.createHttpClient();
988993
}
989994

990-
public Ratelimiter getIpAttemptLimiter() {
995+
public @MonotonicNonNull Ratelimiter<InetAddress> getIpAttemptLimiter() {
991996
return ipAttemptLimiter;
992997
}
993998

999+
public @MonotonicNonNull Ratelimiter<UUID> getCommandRateLimiter() {
1000+
return commandRateLimiter;
1001+
}
1002+
1003+
public @MonotonicNonNull Ratelimiter<UUID> getTabCompleteRateLimiter() {
1004+
return tabCompleteRateLimiter;
1005+
}
1006+
9941007
/**
9951008
* Checks if the {@code connection} can be registered with the proxy.
9961009
*

proxy/src/main/java/com/velocitypowered/proxy/command/VelocityCommandManager.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ public CompletableFuture<Boolean> executeImmediatelyAsync(
293293

294294
return CompletableFuture.supplyAsync(
295295
() -> this.parse(cmdLine, source), figureAsyncExecutorForParsing()
296-
).thenComposeAsync(
296+
).thenCompose(
297297
parsed -> CompletableFuture.supplyAsync(
298298
() -> executeImmediately0(source, parsed), this.getAsyncExecutor(parsed)
299299
)
@@ -310,7 +310,7 @@ public CompletableFuture<Boolean> executeImmediatelyAsync(
310310
public CompletableFuture<List<String>> offerSuggestions(final CommandSource source,
311311
final String cmdLine) {
312312
return offerBrigadierSuggestions(source, cmdLine)
313-
.thenApplyAsync(suggestions -> Lists.transform(suggestions.getList(), Suggestion::getText));
313+
.thenApply(suggestions -> Lists.transform(suggestions.getList(), Suggestion::getText));
314314
}
315315

316316
/**

proxy/src/main/java/com/velocitypowered/proxy/command/registrar/InvocableCommandRegistrar.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ private LiteralCommandNode<CommandSource> createLiteral(final T command, final C
104104
.executes(callback)
105105
.suggests((context, builder) -> {
106106
final I invocation = invocationFactory.create(context);
107-
return command.suggestAsync(invocation).thenApplyAsync(suggestions -> {
107+
return command.suggestAsync(invocation).thenApply(suggestions -> {
108108
for (String value : suggestions) {
109109
Preconditions.checkNotNull(value, "suggestion");
110110
builder.suggest(value);

0 commit comments

Comments
 (0)