Skip to content
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
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,9 @@ and you can configure it from there.

Alternatively, you can get the proxy JAR from the [downloads](https://papermc.io/downloads/velocity)
page.

# Localisation

Translations are handled using [Crowdin](https://papermc-io.crowdin.com/velocity).
If you want to translate a language not available on Crowdin,
you might want to ask in the [Discord](https://discord.gg/papermc) about it.
2 changes: 1 addition & 1 deletion api/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ tasks {

val o = options as StandardJavadocDocletOptions
o.encoding = "UTF-8"
o.source = "17"
o.source = "21"

o.use()
o.links(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,22 @@ public interface CommandSource extends Audience, PermissionSubject {
* Sends a message with the MiniMessage format to this source.
*
* @param message MiniMessage content
* @see <a href="https://docs.advntr.dev/minimessage/format.html">MiniMessage docs</a>
* @see <a href="https://docs.papermc.io/adventure/minimessage/format/">MiniMessage docs</a>
* for more information on the format.
**/
default void sendRichMessage(final @NotNull String message) {
this.sendMessage(MiniMessage.miniMessage().deserialize(message, this));
}

/**
* Sends a message with the MiniMessage format to this source.
*
* @param message MiniMessage content
* @param resolvers resolvers to use
* @see <a href="https://docs.advntr.dev/minimessage/">MiniMessage docs</a>
* and <a href="https://docs.advntr.dev/minimessage/dynamic-replacements">MiniMessage Placeholders docs</a>
* for more information on the format.
**/
* Sends a message with the MiniMessage format to this source.
*
* @param message MiniMessage content
* @param resolvers resolvers to use
* @see <a href="https://docs.papermc.io/adventure/minimessage/">MiniMessage docs</a>
* and <a href="https://docs.papermc.io/adventure/minimessage/dynamic-replacements">MiniMessage Placeholders docs</a>
* for more information on the format.
*/
default void sendRichMessage(
final @NotNull String message,
final @NotNull TagResolver @NotNull... resolvers
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.velocitypowered.api.event.ResultedEvent;
import com.velocitypowered.api.event.annotation.AwaitingEvent;
import com.velocitypowered.api.proxy.Player;
import org.checkerframework.checker.nullness.qual.Nullable;

/**
* This event is fired once the player has been authenticated, but before they connect to a server.
Expand All @@ -22,17 +23,41 @@
public final class LoginEvent implements ResultedEvent<ResultedEvent.ComponentResult> {

private final Player player;
private final String serverIdHash;
private ComponentResult result;

@Deprecated(forRemoval = true)
public LoginEvent(Player player) {
this(player, null);
}

/**
* Constructs a new {@link LoginEvent}.
*
* @param player the player who has completed authentication
* @param serverIdHash the server ID hash sent to Mojang for authentication,
* or {@code null} if the connection is in offline-mode
*/
public LoginEvent(Player player, @Nullable String serverIdHash) {
this.player = Preconditions.checkNotNull(player, "player");
this.serverIdHash = serverIdHash;
this.result = ComponentResult.allowed();
}

public Player getPlayer() {
return player;
}

/**
* Returns the server ID hash that was sent to Mojang to authenticate the player.
* If the connection was in offline-mode, this returns {@code null}.
*
* @return the server ID hash that was sent to Mojang to authenticate the player
*/
public @Nullable String getServerIdHash() {
return serverIdHash;
}

@Override
public ComponentResult getResult() {
return result;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ public String toString() {
* is used, then {@link ConnectionRequestBuilder#connect()}'s result will have the status
* {@link Status#CONNECTION_CANCELLED}.
*
* @return a result to deny conneections
* @return a result to deny connections
*/
public static ServerResult denied() {
return DENIED;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@ public boolean isSupported() {
MINECRAFT_1_21_6(771, "1.21.6"),
MINECRAFT_1_21_7(772, "1.21.7", "1.21.8"),
MINECRAFT_1_21_9(773, "1.21.9", "1.21.10"),
MINECRAFT_1_21_11(774, "1.21.11");
MINECRAFT_1_21_11(774, "1.21.11"),
MINECRAFT_26_1(775, "26.1", "26.1.1", "26.1.2");

private static final int SNAPSHOT_BIT = 30;

Expand Down
13 changes: 12 additions & 1 deletion api/src/main/java/com/velocitypowered/api/proxy/Player.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.event.HoverEventSource;
import net.kyori.adventure.text.object.PlayerHeadObjectContents;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.jetbrains.annotations.NotNull;

Expand All @@ -49,7 +50,8 @@ public interface Player extends
/* Fundamental Velocity interfaces */
CommandSource, InboundConnection, ChannelMessageSource, ChannelMessageSink,
/* Adventure-specific interfaces */
Identified, HoverEventSource<HoverEvent.ShowEntity>, Keyed, KeyIdentifiable, Sound.Emitter {
Identified, HoverEventSource<HoverEvent.ShowEntity>, Keyed, KeyIdentifiable, Sound.Emitter,
PlayerHeadObjectContents.SkinSource {

/**
* Returns the player's current username.
Expand Down Expand Up @@ -336,6 +338,15 @@ default void clearHeaderAndFooter() {
Component.text(getUsername()))));
}

@SuppressWarnings("UnstableApiUsage") // permitted implementation
@Override
default void applySkinToPlayerHeadContents(
final PlayerHeadObjectContents.@NotNull Builder builder) {
builder.skin(this.getGameProfile());
if (this.hasSentPlayerSettings()) {
builder.hat(this.getPlayerSettings().getSkinParts().hasHat());
}
}

/**
* Gets the player's client brand.
Expand Down
22 changes: 21 additions & 1 deletion api/src/main/java/com/velocitypowered/api/util/GameProfile.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,14 @@
import com.google.common.collect.ImmutableList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import net.kyori.adventure.text.object.PlayerHeadObjectContents;
import org.jetbrains.annotations.NotNull;

/**
* Represents a Mojang game profile. This class is immutable.
*/
public final class GameProfile {
public final class GameProfile implements PlayerHeadObjectContents.SkinSource {

private final UUID id;
private final String undashedId;
Expand Down Expand Up @@ -169,6 +172,23 @@ public static GameProfile forOfflinePlayer(String username) {
ImmutableList.of());
}

@SuppressWarnings("UnstableApiUsage") // permitted implementation
@Override
public void applySkinToPlayerHeadContents(
final PlayerHeadObjectContents.@NotNull Builder builder) {
if (this.properties.isEmpty()) {
builder.id(this.id);
return;
}

builder.id(this.id)
.name(this.name)
.profileProperties(this.properties.stream()
.map(property -> PlayerHeadObjectContents.property(property.getName(),
property.getValue(), property.getSignature()))
.collect(Collectors.toList()));
}

@Override
public String toString() {
return "GameProfile{"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
/*
* Copyright (C) 2025 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 fun.iiii.openvelocity.api.event.connection;

import com.google.common.base.Preconditions;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
/*
* Copyright (C) 2025 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 fun.iiii.openvelocity.api.event.connection;

import com.google.common.base.Preconditions;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
/*
* Copyright (C) 2025 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 fun.iiii.openvelocity.api.event.connection;

import com.google.common.base.Preconditions;
Expand Down
Empty file.
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ subprojects {

java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(17))
languageVersion.set(JavaLanguageVersion.of(21))
}
}

Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
group=com.velocitypowered
version=3.4.0-SNAPSHOT
version=3.5.0-SNAPSHOT
47 changes: 23 additions & 24 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,27 +1,26 @@
[versions]
configurate3 = "3.7.3"
configurate4 = "4.1.2"
configurate4 = "4.2.0"
flare = "2.0.1"
log4j = "2.24.3"
netty = "4.2.7.Final"
log4j = "2.25.3"
netty = "4.2.10.Final"

[plugins]
fill = "io.papermc.fill.gradle:1.0.3"
indra-publishing = "net.kyori.indra.publishing:2.0.6"
shadow = "com.gradleup.shadow:8.3.6"
spotless = "com.diffplug.spotless:6.25.0"
fill = "io.papermc.fill.gradle:1.0.10"
shadow = "com.gradleup.shadow:9.3.1"
spotless = "com.diffplug.spotless:8.2.0"

[libraries]
adventure-bom = "net.kyori:adventure-bom:4.26.1"
adventure-text-serializer-json-legacy-impl = "net.kyori:adventure-text-serializer-json-legacy-impl:4.26.1"
adventure-facet = "net.kyori:adventure-platform-facet:4.3.4"
asm = "org.ow2.asm:asm:9.8"
auto-service = "com.google.auto.service:auto-service:1.0.1"
auto-service-annotations = "com.google.auto.service:auto-service-annotations:1.0.1"
adventure-facet = "net.kyori:adventure-platform-facet:4.4.1"
asm = "org.ow2.asm:asm:9.9.1"
auto-service = "com.google.auto.service:auto-service:1.1.1"
auto-service-annotations = "com.google.auto.service:auto-service-annotations:1.1.1"
brigadier = "com.velocitypowered:velocity-brigadier:1.0.0-SNAPSHOT"
bstats = "org.bstats:bstats-base:3.0.3"
caffeine = "com.github.ben-manes.caffeine:caffeine:3.1.8"
checker-qual = "org.checkerframework:checker-qual:3.42.0"
bstats = "org.bstats:bstats-base:3.1.0"
caffeine = "com.github.ben-manes.caffeine:caffeine:3.2.3"
checker-qual = "org.checkerframework:checker-qual:3.53.0"
checkstyle = "com.puppycrawl.tools:checkstyle:10.9.3"
completablefutures = "com.spotify:completable-futures:0.3.6"
configurate3-hocon = { module = "org.spongepowered:configurate-hocon", version.ref = "configurate3" }
Expand All @@ -34,32 +33,32 @@ disruptor = "com.lmax:disruptor:4.0.0"
fastutil = "it.unimi.dsi:fastutil:8.5.15"
flare-core = { module = "space.vectrix.flare:flare", version.ref = "flare" }
flare-fastutil = { module = "space.vectrix.flare:flare-fastutil", version.ref = "flare" }
jline = "org.jline:jline-terminal-jansi:3.30.2"
jline = "org.jline:jline-terminal-jansi:3.30.6"
jopt = "net.sf.jopt-simple:jopt-simple:5.0.4"
junit = "org.junit.jupiter:junit-jupiter:5.10.2"
jspecify = "org.jspecify:jspecify:0.3.0"
junit = "org.junit.jupiter:junit-jupiter:5.14.2"
jspecify = "org.jspecify:jspecify:1.0.0"
kyori-ansi = "net.kyori:ansi:1.1.1"
guava = "com.google.guava:guava:25.1-jre"
gson = "com.google.code.gson:gson:2.10.1"
guice = "com.google.inject:guice:6.0.0"
guava = "com.google.guava:guava:33.5.0-jre"
gson = "com.google.code.gson:gson:2.13.2"
guice = "com.google.inject:guice:7.0.0"
lmbda = "org.lanternpowered:lmbda:2.0.0"
log4j-api = { module = "org.apache.logging.log4j:log4j-api", version.ref = "log4j" }
log4j-core = { module = "org.apache.logging.log4j:log4j-core", version.ref = "log4j" }
log4j-slf4j-impl = { module = "org.apache.logging.log4j:log4j-slf4j2-impl", version.ref = "log4j" }
log4j-iostreams = { module = "org.apache.logging.log4j:log4j-iostreams", version.ref = "log4j" }
log4j-jul = { module = "org.apache.logging.log4j:log4j-jul", version.ref = "log4j" }
mockito = "org.mockito:mockito-core:5.10.0"
mockito = "org.mockito:mockito-core:5.21.0"
netty-codec = { module = "io.netty:netty-codec", version.ref = "netty" }
netty-codec-haproxy = { module = "io.netty:netty-codec-haproxy", version.ref = "netty" }
netty-codec-http = { module = "io.netty:netty-codec-http", version.ref = "netty" }
netty-handler = { module = "io.netty:netty-handler", version.ref = "netty" }
netty-transport-native-epoll = { module = "io.netty:netty-transport-native-epoll", version.ref = "netty" }
netty-transport-native-kqueue = { module = "io.netty:netty-transport-native-kqueue", version.ref = "netty" }
netty-transport-native-iouring = { module = "io.netty:netty-transport-native-io_uring", version.ref = "netty" }
nightconfig = "com.electronwill.night-config:toml:3.6.7"
nightconfig = "com.electronwill.night-config:toml:3.8.3"
slf4j = "org.slf4j:slf4j-api:2.0.17"
snakeyaml = "org.yaml:snakeyaml:1.33"
spotbugs-annotations = "com.github.spotbugs:spotbugs-annotations:4.7.3"
snakeyaml = "org.yaml:snakeyaml:2.5"
spotbugs-annotations = "com.github.spotbugs:spotbugs-annotations:4.9.8"
terminalconsoleappender = "net.minecrell:terminalconsoleappender:1.3.0"

[bundles]
Expand Down
Binary file modified gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-bin.zip
distributionUrl=https://mirrors.huaweicloud.com/gradle/gradle-9.3.1-all.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Expand Down
16 changes: 6 additions & 10 deletions gradlew

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading