-
Notifications
You must be signed in to change notification settings - Fork 25
Add support for GlobalTranslator #40
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| package me.tofaa.entitylib; | ||
|
|
||
| import java.util.Locale; | ||
| import java.util.UUID; | ||
|
|
||
| public interface UserLocaleProvider { | ||
| Locale locale(UUID user); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| package me.tofaa.entitylib.utils; | ||
|
|
||
| import com.github.retrooper.packetevents.protocol.entity.data.EntityData; | ||
| import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes; | ||
| import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityMetadata; | ||
| import me.tofaa.entitylib.EntityLib; | ||
| import java.util.Locale; | ||
| import java.util.Optional; | ||
| import java.util.UUID; | ||
| import net.kyori.adventure.text.Component; | ||
| import net.kyori.adventure.translation.GlobalTranslator; | ||
|
|
||
| public class PacketUtil { | ||
| private PacketUtil() { | ||
| } | ||
|
|
||
| public static void renderPacket(UUID user, WrapperPlayServerEntityMetadata metadata) { | ||
| Locale locale = EntityLib.getApi().getUserLocaleProvider().locale(user); | ||
| for (final EntityData<?> entityData : metadata.getEntityMetadata()) { | ||
| if (entityData.getType() == EntityDataTypes.ADV_COMPONENT) { | ||
| Component component = (Component) entityData.getValue(); | ||
| final Component rendered = GlobalTranslator.render(component, locale); | ||
| ((EntityData<Component>) entityData).setValue(rendered); | ||
| } else if (entityData.getType() == EntityDataTypes.OPTIONAL_ADV_COMPONENT) { | ||
| final Optional<Component> optional = (Optional<Component>) entityData.getValue(); | ||
| if (optional.isPresent()) { | ||
| final Component component = optional.get(); | ||
| final Component rendered = GlobalTranslator.render(component, locale); | ||
| ((EntityData<Optional<Component>>) entityData).setValue(Optional.of(rendered)); | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
Comment on lines
+17
to
+33
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Core logic is sound but needs safety improvements. The method correctly handles both
Consider adding safety checks: public static void renderPacket(UUID user, WrapperPlayServerEntityMetadata metadata) {
+ UserLocaleProvider provider = EntityLib.getApi().getUserLocaleProvider();
+ if (provider == null) return;
+
- Locale locale = EntityLib.getApi().getUserLocaleProvider().locale(user);
+ Locale locale = provider.locale(user);
+ if (locale == null) return;
+
for (final EntityData<?> entityData : metadata.getEntityMetadata()) {
if (entityData.getType() == EntityDataTypes.ADV_COMPONENT) {
- Component component = (Component) entityData.getValue();
+ Object value = entityData.getValue();
+ if (!(value instanceof Component)) continue;
+ Component component = (Component) value;
+ if (component == null) continue;
final Component rendered = GlobalTranslator.render(component, locale);
((EntityData<Component>) entityData).setValue(rendered);
} else if (entityData.getType() == EntityDataTypes.OPTIONAL_ADV_COMPONENT) {
- final Optional<Component> optional = (Optional<Component>) entityData.getValue();
+ Object value = entityData.getValue();
+ if (!(value instanceof Optional)) continue;
+ final Optional<Component> optional = (Optional<Component>) value;
if (optional.isPresent()) {
final Component component = optional.get();
+ if (component == null) continue;
final Component rendered = GlobalTranslator.render(component, locale);
((EntityData<Optional<Component>>) entityData).setValue(Optional.of(rendered));
}
}
}
}🤖 Prompt for AI Agents |
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,25 +5,39 @@ | |
| import com.github.retrooper.packetevents.protocol.world.Location; | ||
| import com.github.retrooper.packetevents.util.Vector3d; | ||
| import com.github.retrooper.packetevents.wrapper.PacketWrapper; | ||
| import com.github.retrooper.packetevents.wrapper.play.server.*; | ||
| import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerBundle; | ||
| import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerDestroyEntities; | ||
| import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityHeadLook; | ||
| import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityMetadata; | ||
| import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityRotation; | ||
| import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityTeleport; | ||
| import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityVelocity; | ||
| import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSetPassengers; | ||
| import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSpawnEntity; | ||
| import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSystemChatMessage; | ||
| import me.tofaa.entitylib.EntityLib; | ||
| import me.tofaa.entitylib.container.EntityContainer; | ||
| import me.tofaa.entitylib.meta.EntityMeta; | ||
| import me.tofaa.entitylib.meta.types.ObjectData; | ||
| import me.tofaa.entitylib.tick.Tickable; | ||
| import me.tofaa.entitylib.utils.PacketUtil; | ||
| import me.tofaa.entitylib.ve.ViewerRule; | ||
| import me.tofaa.entitylib.wrapper.spawning.SpawnPacketProvider; | ||
| import java.util.Collection; | ||
| import java.util.Collections; | ||
| import java.util.List; | ||
| import java.util.Optional; | ||
| import java.util.Set; | ||
| import java.util.UUID; | ||
| import java.util.concurrent.ConcurrentHashMap; | ||
| import java.util.concurrent.CopyOnWriteArrayList; | ||
| import java.util.function.Consumer; | ||
| import net.kyori.adventure.text.Component; | ||
| import org.jetbrains.annotations.ApiStatus; | ||
| import org.jetbrains.annotations.NotNull; | ||
| import org.jetbrains.annotations.Nullable; | ||
| import org.jetbrains.annotations.UnmodifiableView; | ||
|
|
||
| import java.util.*; | ||
| import java.util.concurrent.ConcurrentHashMap; | ||
| import java.util.concurrent.CopyOnWriteArrayList; | ||
| import java.util.function.Consumer; | ||
|
|
||
| public class WrapperEntity implements Tickable { | ||
| private final UUID uuid; | ||
| private final int entityId; | ||
|
|
@@ -510,6 +524,11 @@ private static void sendPacket(UUID user, PacketWrapper<?> wrapper) { | |
| return; | ||
| } | ||
|
|
||
| // Special handling for entity metadata packets to support `GlobalTranslator` functionality and component rendering | ||
| if (wrapper instanceof WrapperPlayServerEntityMetadata) { | ||
| PacketUtil.renderPacket(user, (WrapperPlayServerEntityMetadata) wrapper); | ||
| } | ||
|
Comment on lines
+527
to
+530
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Verification agent 🧩 Analysis chainGood integration of locale-aware component rendering. The special handling for entity metadata packets is well-implemented and properly placed before packet transmission. The instanceof check is efficient and the cast is safe. Consider adding error handling around 🏁 Script executed: #!/bin/bash
# Verify PacketUtil.renderPacket error handling
rg -A 10 -B 5 "renderPacket.*throws|catch.*renderPacket" --type javaLength of output: 70 🏁 Script executed: #!/bin/bash
# Locate PacketUtil class and inspect renderPacket method declaration for exception behavior
rg -n "class PacketUtil" --type java
rg -A5 -B2 "renderPacket(" --type javaLength of output: 244 🏁 Script executed: #!/bin/bash
# Find all occurrences of `renderPacket` to locate its definition
rg -n "renderPacket" --type java
# Once the file is identified, show the method declaration with surrounding context
rg -C5 "renderPacket" api/src/main/java/me/tofaa/entitylib/utils/PacketUtil.javaLength of output: 964 Add runtime error handling around The • File: api/src/main/java/me/tofaa/entitylib/wrapper/WrapperEntity.java Suggested diff: - if (wrapper instanceof WrapperPlayServerEntityMetadata) {
- PacketUtil.renderPacket(user, (WrapperPlayServerEntityMetadata) wrapper);
- }
+ if (wrapper instanceof WrapperPlayServerEntityMetadata) {
+ try {
+ PacketUtil.renderPacket(user, (WrapperPlayServerEntityMetadata) wrapper);
+ } catch (RuntimeException e) {
+ EntityLib.getLogger()
+ .error("Failed to render entity metadata packet for user {}", user, e);
+ }
+ }🤖 Prompt for AI Agents |
||
|
|
||
| EntityLib.getApi().getPacketEvents().getProtocolManager().sendPacket(channel, wrapper); | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,73 @@ | ||||||||||||||||||||||||||||||||||
| package me.tofaa.entitylib.spigot; | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| import me.tofaa.entitylib.UserLocaleProvider; | ||||||||||||||||||||||||||||||||||
| import java.lang.invoke.MethodHandle; | ||||||||||||||||||||||||||||||||||
| import java.lang.invoke.MethodHandles; | ||||||||||||||||||||||||||||||||||
| import java.lang.invoke.MethodType; | ||||||||||||||||||||||||||||||||||
| import java.util.Locale; | ||||||||||||||||||||||||||||||||||
| import java.util.UUID; | ||||||||||||||||||||||||||||||||||
| import java.util.function.Function; | ||||||||||||||||||||||||||||||||||
| import net.kyori.adventure.translation.Translator; | ||||||||||||||||||||||||||||||||||
| import org.bukkit.Bukkit; | ||||||||||||||||||||||||||||||||||
| import org.bukkit.entity.Player; | ||||||||||||||||||||||||||||||||||
| import org.jetbrains.annotations.NotNull; | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||
| * This implementation is based on code from the scoreboard-library project: | ||||||||||||||||||||||||||||||||||
| * <a href="https://github.com/MegavexNetwork/scoreboard-library/blob/bc8e3c2d2ecf9973ec0d6bb8ae4af94ed008b360/commons/src/main/java/net/megavex/scoreboardlibrary/implementation/commons/LocaleProvider.java">LocaleProvider</a> | ||||||||||||||||||||||||||||||||||
| * Modified and adapted for use in EntityLib. | ||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||
| public class SpigotPlayerLocaleProvider implements UserLocaleProvider { | ||||||||||||||||||||||||||||||||||
| private static final Locale DEFAULT_LOCALE = Locale.US; | ||||||||||||||||||||||||||||||||||
| private static final Function<Player, Locale> provider = get(); | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| @Override | ||||||||||||||||||||||||||||||||||
| public Locale locale(final UUID user) { | ||||||||||||||||||||||||||||||||||
| final Player player = Bukkit.getPlayer(user); | ||||||||||||||||||||||||||||||||||
| return player == null ? DEFAULT_LOCALE : provider.apply(player); | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+26
to
+29
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Verification agent 🧩 Analysis chainConsider handling potential race conditions There's a potential race condition where a player could disconnect between the null check and @Override
public Locale locale(final UUID user) {
final Player player = Bukkit.getPlayer(user);
- return player == null ? DEFAULT_LOCALE : provider.apply(player);
+ if (player == null) {
+ return DEFAULT_LOCALE;
+ }
+ try {
+ return provider.apply(player);
+ } catch (RuntimeException e) {
+ // Player might have disconnected or other issues
+ return DEFAULT_LOCALE;
+ }
}🏁 Script executed: #!/bin/bash
# Locate and display the SpigotPlayerLocaleProvider implementation for review
fd SpigotPlayerLocaleProvider.java -type f -x sed -n '1,200p' {}Length of output: 237 🏁 Script executed: #!/bin/bash
# Corrected script to locate and display the SpigotPlayerLocaleProvider implementation
file=$(find . -type f -name SpigotPlayerLocaleProvider.java)
if [ -z "$file" ]; then
echo "SpigotPlayerLocaleProvider.java not found"
exit 1
fi
echo "Found file at: $file"
sed -n '1,200p' "$file"Length of output: 3649 Handle reflection exceptions in Wrap the call to Locations to update:
Suggested diff: @Override
public Locale locale(final UUID user) {
final Player player = Bukkit.getPlayer(user);
- return player == null ? DEFAULT_LOCALE : provider.apply(player);
+ if (player == null) {
+ return DEFAULT_LOCALE;
+ }
+ try {
+ return provider.apply(player);
+ } catch (RuntimeException e) {
+ // Fallback to default locale if reflective lookup fails
+ return DEFAULT_LOCALE;
+ }
}🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| private static @NotNull Function<Player, Locale> get() { | ||||||||||||||||||||||||||||||||||
| MethodHandles.Lookup lookup = MethodHandles.publicLookup(); | ||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||
| MethodHandle adventureMethod = lookup.findVirtual(Player.class, "locale", MethodType.methodType(Locale.class)); | ||||||||||||||||||||||||||||||||||
| return player -> { | ||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||
| return (Locale) adventureMethod.invokeExact(player); | ||||||||||||||||||||||||||||||||||
| } catch (Throwable e) { | ||||||||||||||||||||||||||||||||||
| throw new RuntimeException(e); | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+35
to
+41
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Preserve stack traces when rethrowing exceptions When catching and rethrowing exceptions, preserve the original stack trace for better debugging. return player -> {
try {
return (Locale) adventureMethod.invokeExact(player);
} catch (Throwable e) {
- throw new RuntimeException(e);
+ throw new RuntimeException("Failed to get locale via Adventure API", e);
}
};📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||
| } catch (IllegalAccessException | NoSuchMethodException ignored) { | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| MethodType methodType = MethodType.methodType(String.class); | ||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||
| MethodHandle legacySpigotMethod = lookup.findVirtual(Player.Spigot.class, "getLocale", methodType); | ||||||||||||||||||||||||||||||||||
| return player -> { | ||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||
| Locale locale = Translator.parseLocale((String) legacySpigotMethod.invokeExact(player.spigot())); | ||||||||||||||||||||||||||||||||||
| return locale == null ? DEFAULT_LOCALE : locale; | ||||||||||||||||||||||||||||||||||
| } catch (Throwable e) { | ||||||||||||||||||||||||||||||||||
| throw new RuntimeException(e); | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+48
to
+55
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Apply consistent exception handling improvements Similar to the previous comment, improve exception messages here too. return player -> {
try {
Locale locale = Translator.parseLocale((String) legacySpigotMethod.invokeExact(player.spigot()));
return locale == null ? DEFAULT_LOCALE : locale;
} catch (Throwable e) {
- throw new RuntimeException(e);
+ throw new RuntimeException("Failed to get locale via legacy Spigot API", e);
}
};📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||
| } catch (IllegalAccessException | NoSuchMethodException ignored) { | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||
| MethodHandle legacyMethod = lookup.findVirtual(Player.class, "getLocale", methodType); | ||||||||||||||||||||||||||||||||||
| return player -> { | ||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||
| Locale locale = Translator.parseLocale((String) legacyMethod.invokeExact(player)); | ||||||||||||||||||||||||||||||||||
| return locale == null ? DEFAULT_LOCALE : locale; | ||||||||||||||||||||||||||||||||||
| } catch (Throwable e) { | ||||||||||||||||||||||||||||||||||
| throw new RuntimeException(e); | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+61
to
+68
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Apply consistent exception handling improvements Apply the same exception handling improvement here. return player -> {
try {
Locale locale = Translator.parseLocale((String) legacyMethod.invokeExact(player));
return locale == null ? DEFAULT_LOCALE : locale;
} catch (Throwable e) {
- throw new RuntimeException(e);
+ throw new RuntimeException("Failed to get locale via legacy API", e);
}
};📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||
| } catch (IllegalAccessException | NoSuchMethodException ignored) { | ||||||||||||||||||||||||||||||||||
| throw new RuntimeException("No way to get players locale found"); | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,13 +9,15 @@ | |
| import io.github.retrooper.packetevents.velocity.factory.VelocityPacketEventsBuilder; | ||
| import me.tofaa.entitylib.APIConfig; | ||
| import me.tofaa.entitylib.EntityLibAPI; | ||
| import me.tofaa.entitylib.UserLocaleProvider; | ||
| import me.tofaa.entitylib.common.AbstractPlatform; | ||
| import org.jetbrains.annotations.NotNull; | ||
|
|
||
| import java.util.logging.Logger; | ||
|
|
||
| public class VelocityEntityLibPlatform extends AbstractPlatform<ProxyServer> { | ||
| private VelocityEntityLibAPI api; | ||
| private UserLocaleProvider userLocaleProvider; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing field initialization could cause NPE. The -private UserLocaleProvider userLocaleProvider;
+private UserLocaleProvider userLocaleProvider = new VelocityPlayerLocaleProvider(handle);Or provide a safe fallback: -private UserLocaleProvider userLocaleProvider;
+private UserLocaleProvider userLocaleProvider = (user) -> Locale.US;
🤖 Prompt for AI Agents |
||
| private Object plugin; | ||
|
|
||
| public VelocityEntityLibPlatform(Object plugin, ProxyServer handle) { | ||
|
|
@@ -54,4 +56,14 @@ public EntityLibAPI<?> getAPI() { | |
| public String getName() { | ||
| return "Velocity"; | ||
| } | ||
|
|
||
| @Override | ||
| public @NotNull UserLocaleProvider getUserLocaleProvider() { | ||
| return userLocaleProvider; | ||
| } | ||
|
|
||
| @Override | ||
| public void setUserLocaleProvider(final UserLocaleProvider userLocaleProvider) { | ||
| this.userLocaleProvider = userLocaleProvider; | ||
| } | ||
|
Comment on lines
+60
to
+68
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @NotNull annotation inconsistent with nullable field. The Either initialize the field with a default value or remove the 🤖 Prompt for AI Agents |
||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,20 @@ | ||||||||||||||||||||||||||||||||||||||||||||
| package me.tofaa.entitylib.velocity; | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| import com.velocitypowered.api.proxy.Player; | ||||||||||||||||||||||||||||||||||||||||||||
| import com.velocitypowered.api.proxy.ProxyServer; | ||||||||||||||||||||||||||||||||||||||||||||
| import me.tofaa.entitylib.UserLocaleProvider; | ||||||||||||||||||||||||||||||||||||||||||||
| import java.util.Locale; | ||||||||||||||||||||||||||||||||||||||||||||
| import java.util.UUID; | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| public class VelocityPlayerLocaleProvider implements UserLocaleProvider { | ||||||||||||||||||||||||||||||||||||||||||||
| private final ProxyServer proxyServer; | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| public VelocityPlayerLocaleProvider(final ProxyServer proxyServer) { | ||||||||||||||||||||||||||||||||||||||||||||
| this.proxyServer = proxyServer; | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+9
to
+14
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add null validation and documentation. The constructor lacks null validation and the class needs documentation to explain its purpose. +import java.util.Objects;
+
+/**
+ * Velocity platform implementation of {@link UserLocaleProvider}.
+ * Retrieves player locales from the Velocity proxy server.
+ */
public class VelocityPlayerLocaleProvider implements UserLocaleProvider {
private final ProxyServer proxyServer;
public VelocityPlayerLocaleProvider(final ProxyServer proxyServer) {
- this.proxyServer = proxyServer;
+ this.proxyServer = Objects.requireNonNull(proxyServer, "proxyServer cannot be null");
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| @Override | ||||||||||||||||||||||||||||||||||||||||||||
| public Locale locale(final UUID user) { | ||||||||||||||||||||||||||||||||||||||||||||
| return proxyServer.getPlayer(user).map(Player::getEffectiveLocale).orElse(Locale.US); | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+16
to
+19
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Consider method naming consistency and add null annotations. The method should align with interface improvements and include proper null safety. + import org.jetbrains.annotations.NotNull;
+
@Override
- public Locale locale(final UUID user) {
+ public @NotNull Locale getUserLocale(@NotNull final UUID user) {
+ Objects.requireNonNull(user, "user cannot be null");
return proxyServer.getPlayer(user).map(Player::getEffectiveLocale).orElse(Locale.US);
}Note: This assumes the interface method name is updated as suggested in the earlier review.
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add null annotations and documentation for better API clarity.
The interface lacks proper documentation and null safety annotations. Consider the following improvements:
The method name
localeshould also be more descriptive -getUserLocaleclearly indicates what the method does.📝 Committable suggestion
🤖 Prompt for AI Agents