mirror of
https://github.com/GeyserMC/Floodgate.git
synced 2026-01-04 15:31:48 +00:00
Introduced connectionByPlatformIdentifier, removed guava usage
This commit is contained in:
@@ -25,13 +25,13 @@
|
||||
|
||||
package org.geysermc.floodgate.core.addon.data;
|
||||
|
||||
import com.google.common.collect.Queues;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
import io.netty.util.AttributeKey;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.geysermc.floodgate.api.handshake.HandshakeData;
|
||||
import org.geysermc.floodgate.core.config.FloodgateConfig;
|
||||
@@ -48,7 +48,7 @@ public abstract class CommonDataHandler extends ChannelInboundHandlerAdapter {
|
||||
protected final AttributeKey<String> kickMessageAttribute;
|
||||
protected final PacketBlocker blocker;
|
||||
|
||||
protected final Queue<Object> packetQueue = Queues.newConcurrentLinkedQueue();
|
||||
protected final Queue<Object> packetQueue = new ConcurrentLinkedQueue<>();
|
||||
protected Object handshakePacket;
|
||||
protected ChannelHandlerContext ctx;
|
||||
|
||||
|
||||
@@ -25,10 +25,10 @@
|
||||
|
||||
package org.geysermc.floodgate.core.addon.data;
|
||||
|
||||
import com.google.common.collect.Queues;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
/**
|
||||
* In Floodgate the PacketBlocker is used to temporarily prevent packets from being decoded. A
|
||||
@@ -44,7 +44,7 @@ import java.util.Queue;
|
||||
* caused the server to switch to the login state.
|
||||
*/
|
||||
public class PacketBlocker extends ChannelInboundHandlerAdapter {
|
||||
private final Queue<Object> packetQueue = Queues.newConcurrentLinkedQueue();
|
||||
private final Queue<Object> packetQueue = new ConcurrentLinkedQueue<>();
|
||||
private volatile boolean blockPackets;
|
||||
|
||||
private ChannelHandlerContext ctx;
|
||||
|
||||
@@ -25,17 +25,12 @@
|
||||
|
||||
package org.geysermc.floodgate.core.api;
|
||||
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import io.micronaut.context.BeanProvider;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.api.GeyserApiBase;
|
||||
@@ -47,6 +42,7 @@ import org.geysermc.floodgate.api.link.PlayerLink;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.core.config.FloodgateConfig;
|
||||
import org.geysermc.floodgate.core.http.xbox.XboxClient;
|
||||
import org.geysermc.floodgate.core.player.ConnectionManager;
|
||||
import org.geysermc.floodgate.core.pluginmessage.PluginMessageManager;
|
||||
import org.geysermc.floodgate.core.pluginmessage.channel.FormChannel;
|
||||
import org.geysermc.floodgate.core.pluginmessage.channel.TransferChannel;
|
||||
@@ -55,12 +51,7 @@ import org.geysermc.floodgate.core.scope.ServerOnly;
|
||||
@ServerOnly
|
||||
@Singleton
|
||||
public class SimpleFloodgateApi implements GeyserApiBase {
|
||||
private final Map<UUID, Connection> players = new ConcurrentHashMap<>();
|
||||
private final Cache<UUID, Connection> pendingRemove =
|
||||
CacheBuilder.newBuilder()
|
||||
.expireAfterWrite(20, TimeUnit.SECONDS)
|
||||
.build();
|
||||
|
||||
@Inject ConnectionManager connectionManager;
|
||||
@Inject BeanProvider<PluginMessageManager> pluginMessageManager;
|
||||
@Inject FloodgateConfig config;
|
||||
@Inject FloodgateLogger logger;
|
||||
@@ -73,12 +64,12 @@ public class SimpleFloodgateApi implements GeyserApiBase {
|
||||
|
||||
@Override
|
||||
public @NonNull List<? extends Connection> onlineConnections() {
|
||||
return ImmutableList.copyOf(players.values());
|
||||
return new ArrayList<>(connectionManager.acceptedConnections());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onlineConnectionsCount() {
|
||||
return players.size();
|
||||
return connectionManager.acceptedConnectionsCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -88,31 +79,16 @@ public class SimpleFloodgateApi implements GeyserApiBase {
|
||||
|
||||
@Override
|
||||
public @Nullable Connection connectionByUuid(@NonNull UUID uuid) {
|
||||
Connection selfPlayer = players.get(uuid);
|
||||
if (selfPlayer != null) {
|
||||
return selfPlayer;
|
||||
}
|
||||
return connectionManager.connectionByUuid(uuid);
|
||||
}
|
||||
|
||||
// bedrock players are always stored by their xuid,
|
||||
// so we return the instance if we know that the given uuid is a Floodgate uuid
|
||||
if (isFloodgateId(uuid)) {
|
||||
return pendingRemove.getIfPresent(uuid);
|
||||
}
|
||||
|
||||
// make it possible to find player by Java id (linked players)
|
||||
// TODO still needed?
|
||||
for (Connection player : players.values()) {
|
||||
if (player.javaUuid().equals(uuid)) {
|
||||
return player;
|
||||
}
|
||||
}
|
||||
// and don't forget the pending remove linked players
|
||||
return getPendingRemovePlayer(uuid);
|
||||
public @Nullable Connection connectionByPlatformIdentifier(@NonNull Object platformIdentifier) {
|
||||
return connectionManager.connectionByPlatformIdentifier(platformIdentifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Connection connectionByXuid(@NonNull String s) {
|
||||
return null;
|
||||
public @Nullable Connection connectionByXuid(@NonNull String xuid) {
|
||||
return connectionManager.connectionByXuid(xuid);
|
||||
}
|
||||
|
||||
public boolean isFloodgateId(UUID uuid) {
|
||||
@@ -157,43 +133,6 @@ public class SimpleFloodgateApi implements GeyserApiBase {
|
||||
}
|
||||
*/
|
||||
|
||||
public Connection addPlayer(Connection player) {
|
||||
// Bedrock players are always stored by their xuid
|
||||
return players.put(player.javaUuid(), player);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is invoked when the player is no longer on the server, but the related platform-
|
||||
* dependant event hasn't fired yet
|
||||
* @param player
|
||||
*/
|
||||
public boolean setPendingRemove(Connection player) {
|
||||
pendingRemove.put(player.javaUuid(), player);
|
||||
return players.remove(player.javaUuid(), player);
|
||||
}
|
||||
|
||||
public void playerRemoved(UUID correctUuid) {
|
||||
// we can remove the player directly if it is a Floodgate UUID.
|
||||
// since it's stored by their Floodgate UUID
|
||||
if (isFloodgateId(correctUuid)) {
|
||||
pendingRemove.invalidate(correctUuid);
|
||||
return;
|
||||
}
|
||||
Connection linkedPlayer = getPendingRemovePlayer(correctUuid);
|
||||
if (linkedPlayer != null) {
|
||||
pendingRemove.invalidate(linkedPlayer.javaUuid());
|
||||
}
|
||||
}
|
||||
|
||||
private Connection getPendingRemovePlayer(UUID correctUuid) {
|
||||
for (Connection player : pendingRemove.asMap().values()) {
|
||||
if (player.javaUuid().equals(correctUuid)) {
|
||||
return player;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public PlayerLink getPlayerLink() { // TODO
|
||||
return InstanceHolder.getPlayerLink();
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import io.micronaut.core.annotation.AnnotationMetadata;
|
||||
import io.micronaut.inject.qualifiers.Qualifiers;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
@@ -40,15 +41,13 @@ import org.geysermc.event.subscribe.Subscribe;
|
||||
import org.geysermc.event.subscribe.Subscriber;
|
||||
import org.geysermc.floodgate.api.event.FloodgateEventBus;
|
||||
import org.geysermc.floodgate.api.event.FloodgateSubscriber;
|
||||
import org.geysermc.floodgate.core.util.EagerSingleton;
|
||||
|
||||
@EagerSingleton
|
||||
@Singleton
|
||||
@SuppressWarnings("unchecked")
|
||||
public final class EventBus extends EventBusImpl<Object, FloodgateSubscriber<?>>
|
||||
public class EventBus extends EventBusImpl<Object, FloodgateSubscriber<?>>
|
||||
implements FloodgateEventBus {
|
||||
@Inject ApplicationContext context;
|
||||
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("rawtypes")
|
||||
public boolean fire(@NonNull Object event) {
|
||||
|
||||
@@ -82,10 +82,10 @@ public abstract class CommandUtil {
|
||||
|
||||
protected abstract Collection<?> getOnlinePlayers();
|
||||
|
||||
public @NonNull Collection<String> getOnlineUsernames(@NonNull PlayerType limitTo) {
|
||||
public @NonNull List<String> getOnlineUsernames(@NonNull PlayerType limitTo) {
|
||||
Collection<?> players = getOnlinePlayers();
|
||||
|
||||
Collection<String> usernames = new ArrayList<>();
|
||||
List<String> usernames = new ArrayList<>();
|
||||
switch (limitTo) {
|
||||
case ALL_PLAYERS:
|
||||
for (Object player : players) {
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2023 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Floodgate
|
||||
*/
|
||||
|
||||
package org.geysermc.floodgate.core.player;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.WeakHashMap;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.api.connection.Connection;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
|
||||
public abstract class ConnectionManager {
|
||||
private final Set<Connection> connections = Collections.synchronizedSet(new HashSet<>());
|
||||
private final Set<Connection> pendingConnections = Collections.synchronizedSet(new HashSet<>());
|
||||
|
||||
private final Map<String, Connection> xuidToConnection =
|
||||
Collections.synchronizedMap(new HashMap<>());
|
||||
private final Map<UUID, Connection> uuidToConnection =
|
||||
Collections.synchronizedMap(new HashMap<>());
|
||||
protected final Map<Object, Connection> platformIdentifierToConnection =
|
||||
Collections.synchronizedMap(new WeakHashMap<>());
|
||||
|
||||
@Inject FloodgateLogger logger;
|
||||
|
||||
public Connection connectionByUuid(UUID javaId) {
|
||||
return uuidToConnection.get(javaId);
|
||||
}
|
||||
|
||||
public Connection connectionByXuid(String xuid) {
|
||||
return xuidToConnection.get(xuid);
|
||||
}
|
||||
|
||||
public @Nullable Connection connectionByPlatformIdentifier(@NonNull Object platformIdentifier) {
|
||||
Objects.requireNonNull(platformIdentifier);
|
||||
var connection = platformIdentifierToConnection.get(platformIdentifier);
|
||||
if (connection != null) {
|
||||
return connection;
|
||||
}
|
||||
// try to fetch a connection or return a different platform identifier we can try
|
||||
var identifierOrConnection = platformIdentifierOrConnectionFor(platformIdentifier);
|
||||
if (identifierOrConnection == null) {
|
||||
return null;
|
||||
}
|
||||
// if it returns a connection it found a way to fetch it from the given platformIdentifier
|
||||
if (identifierOrConnection instanceof Connection foundConnection) {
|
||||
platformIdentifierToConnection.put(platformIdentifier, foundConnection);
|
||||
return foundConnection;
|
||||
}
|
||||
// if it returns a different platform identifier,
|
||||
// call this method again with the new identifier and store the result if it returned any
|
||||
connection = connectionByPlatformIdentifier(identifierOrConnection);
|
||||
if (connection != null) {
|
||||
platformIdentifierToConnection.put(identifierOrConnection, connection);
|
||||
}
|
||||
return connection;
|
||||
}
|
||||
|
||||
protected abstract @Nullable Object platformIdentifierOrConnectionFor(Object input);
|
||||
|
||||
public void addConnection(Connection connection) {
|
||||
connections.add(connection);
|
||||
pendingConnections.add(connection);
|
||||
|
||||
logger.translatedInfo(
|
||||
"floodgate.ingame.login_name",
|
||||
connection.javaUsername(), connection.javaUuid()
|
||||
);
|
||||
}
|
||||
|
||||
public boolean addAcceptedConnection(Connection connection) {
|
||||
pendingConnections.remove(connection);
|
||||
|
||||
xuidToConnection.put(connection.xuid(), connection);
|
||||
var old = uuidToConnection.put(connection.javaUuid(), connection);
|
||||
if (old == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
logger.debug(String.format(
|
||||
"Replaced Floodgate player playing as %s uuid %s with %s uuid %s",
|
||||
old.javaUsername(), old.javaUuid(),
|
||||
connection.javaUsername(), connection.javaUuid()
|
||||
));
|
||||
return true;
|
||||
}
|
||||
|
||||
public Connection findPendingConnection(UUID javaId) {
|
||||
for (Connection pendingConnection : pendingConnections) {
|
||||
if (pendingConnection.javaUuid().equals(javaId)) {
|
||||
return pendingConnection;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void removeConnection(Object platformIdentifier) {
|
||||
var connection = connectionByPlatformIdentifier(platformIdentifier);
|
||||
if (connection == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
connections.remove(connection);
|
||||
pendingConnections.remove(connection);
|
||||
uuidToConnection.remove(connection.javaUuid(), connection);
|
||||
xuidToConnection.remove(connection.xuid(), connection);
|
||||
logger.translatedInfo("floodgate.ingame.disconnect_name", connection.javaUsername());
|
||||
}
|
||||
|
||||
public Collection<Connection> acceptedConnections() {
|
||||
return uuidToConnection.values();
|
||||
}
|
||||
|
||||
public int acceptedConnectionsCount() {
|
||||
return uuidToConnection.size();
|
||||
}
|
||||
}
|
||||
@@ -69,7 +69,7 @@ public final class FloodgateConnection implements Connection {
|
||||
private final PropertyGlue propertyGlue = new PropertyGlue();
|
||||
private LegacyPlayerWrapper legacyPlayer;
|
||||
|
||||
static FloodgateConnection from(BedrockData data, HandshakeData handshakeData, int port) {
|
||||
static FloodgateConnection from(BedrockData data, HandshakeData handshakeData) {
|
||||
UUID javaUniqueId = Utils.getJavaUuid(data.getXuid());
|
||||
|
||||
BedrockPlatform deviceOs = BedrockPlatform.fromId(data.getDeviceOs());
|
||||
@@ -78,7 +78,7 @@ public final class FloodgateConnection implements Connection {
|
||||
|
||||
LinkedPlayer linkedPlayer = handshakeData.getLinkedPlayer();
|
||||
|
||||
InetSocketAddress socketAddress = new InetSocketAddress(data.getIp(), port);
|
||||
InetSocketAddress socketAddress = new InetSocketAddress(data.getIp(), 0);
|
||||
|
||||
return new FloodgateConnection(
|
||||
data.getVersion(), data.getUsername(), handshakeData.getJavaUsername(),
|
||||
|
||||
@@ -29,7 +29,6 @@ import static org.geysermc.floodgate.core.player.FloodgateHandshakeHandler.Resul
|
||||
import static org.geysermc.floodgate.core.player.FloodgateHandshakeHandler.ResultType.NOT_FLOODGATE_DATA;
|
||||
import static org.geysermc.floodgate.util.BedrockData.EXPECTED_LENGTH;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.util.AttributeKey;
|
||||
import it.unimi.dsi.fastutil.Pair;
|
||||
@@ -37,6 +36,7 @@ import it.unimi.dsi.fastutil.objects.ObjectObjectImmutablePair;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Named;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CompletionException;
|
||||
import lombok.AccessLevel;
|
||||
@@ -61,6 +61,7 @@ import org.geysermc.floodgate.util.BedrockData;
|
||||
import org.geysermc.floodgate.util.LinkedPlayer;
|
||||
|
||||
public final class FloodgateHandshakeHandler {
|
||||
@Inject ConnectionManager connectionManager;
|
||||
@Inject HandshakeHandlersImpl handshakeHandlers;
|
||||
@Inject SimpleFloodgateApi api;
|
||||
@Inject CommonPlayerLink link;
|
||||
@@ -106,9 +107,9 @@ public final class FloodgateHandshakeHandler {
|
||||
public CompletableFuture<HandshakeResult> handle(
|
||||
@NonNull Channel channel,
|
||||
@NonNull String floodgateDataString,
|
||||
@NonNull String hostname) {
|
||||
|
||||
byte[] floodgateData = floodgateDataString.getBytes(Charsets.UTF_8);
|
||||
@NonNull String hostname
|
||||
) {
|
||||
byte[] floodgateData = floodgateDataString.getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
|
||||
@@ -193,8 +194,8 @@ public final class FloodgateHandshakeHandler {
|
||||
Channel channel,
|
||||
String hostname,
|
||||
BedrockData bedrockData,
|
||||
LinkedPlayer linkedPlayer) {
|
||||
|
||||
LinkedPlayer linkedPlayer
|
||||
) {
|
||||
try {
|
||||
HandshakeData handshakeData = new HandshakeDataImpl(
|
||||
channel, true, bedrockData.clone(), config,
|
||||
@@ -216,15 +217,12 @@ public final class FloodgateHandshakeHandler {
|
||||
bedrockData.getVerifyCode());
|
||||
}
|
||||
|
||||
int port = ((InetSocketAddress) channel.remoteAddress()).getPort();
|
||||
var connection = FloodgateConnection.from(bedrockData, handshakeData);
|
||||
|
||||
Connection player = FloodgateConnection.from(bedrockData, handshakeData, port);
|
||||
connectionManager.addConnection(connection);
|
||||
channel.attr(playerAttribute).set(connection);
|
||||
|
||||
api.addPlayer(player);
|
||||
|
||||
channel.attr(playerAttribute).set(player);
|
||||
|
||||
return new HandshakeResult(ResultType.SUCCESS, handshakeData, bedrockData, player);
|
||||
return new HandshakeResult(ResultType.SUCCESS, handshakeData, bedrockData, connection);
|
||||
} catch (Exception exception) {
|
||||
exception.printStackTrace();
|
||||
return callHandlerAndReturnResult(ResultType.EXCEPTION, channel, null, hostname);
|
||||
@@ -235,8 +233,8 @@ public final class FloodgateHandshakeHandler {
|
||||
ResultType resultType,
|
||||
Channel channel,
|
||||
BedrockData bedrockData,
|
||||
String hostname) {
|
||||
|
||||
String hostname
|
||||
) {
|
||||
HandshakeData handshakeData = new HandshakeDataImpl(channel, bedrockData != null,
|
||||
bedrockData, config, null, hostname);
|
||||
handshakeHandlers.callHandshakeHandlers(handshakeData);
|
||||
|
||||
@@ -29,7 +29,8 @@ import cloud.commandframework.arguments.CommandArgument;
|
||||
import cloud.commandframework.arguments.parser.ArgumentParseResult;
|
||||
import cloud.commandframework.arguments.parser.ArgumentParser;
|
||||
import cloud.commandframework.context.CommandContext;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Queue;
|
||||
@@ -170,19 +171,19 @@ public class ProfileAudienceArgument extends CommandArgument<UserAudience, Profi
|
||||
String trimmedInput = input.trim();
|
||||
|
||||
if (trimmedInput.isEmpty()) {
|
||||
return ImmutableList.copyOf(commandUtil.getOnlineUsernames(limitTo));
|
||||
return Collections.unmodifiableList(commandUtil.getOnlineUsernames(limitTo));
|
||||
}
|
||||
|
||||
String lowercaseInput = input.toLowerCase(Locale.ROOT);
|
||||
ImmutableList.Builder<String> builder = ImmutableList.builder();
|
||||
List<String> profileSuggestions = new ArrayList<>();
|
||||
|
||||
for (final String player : commandUtil.getOnlineUsernames(limitTo)) {
|
||||
if (player.toLowerCase(Locale.ROOT).startsWith(lowercaseInput)) {
|
||||
builder.add(player);
|
||||
profileSuggestions.add(player);
|
||||
}
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
return Collections.unmodifiableList(profileSuggestions);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -25,11 +25,11 @@
|
||||
|
||||
package org.geysermc.floodgate.core.pluginmessage.channel;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import it.unimi.dsi.fastutil.shorts.Short2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.shorts.Short2ObjectMaps;
|
||||
import it.unimi.dsi.fastutil.shorts.Short2ObjectOpenHashMap;
|
||||
import jakarta.inject.Inject;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import org.geysermc.cumulus.form.Form;
|
||||
@@ -110,7 +110,7 @@ public class FormChannel implements PluginMessageChannel {
|
||||
byte[] jsonData =
|
||||
definition.codec()
|
||||
.jsonData(form)
|
||||
.getBytes(Charsets.UTF_8);
|
||||
.getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
byte[] data = new byte[jsonData.length + 3];
|
||||
data[0] = (byte) definition.formType().ordinal();
|
||||
@@ -123,7 +123,7 @@ public class FormChannel implements PluginMessageChannel {
|
||||
protected boolean callResponseConsumer(byte[] data) {
|
||||
Form storedForm = storedForms.remove(getFormId(data));
|
||||
if (storedForm != null) {
|
||||
String responseData = new String(data, 2, data.length - 2, Charsets.UTF_8);
|
||||
String responseData = new String(data, 2, data.length - 2, StandardCharsets.UTF_8);
|
||||
try {
|
||||
formDefinitions.definitionFor(storedForm)
|
||||
.handleFormResponse(storedForm, responseData);
|
||||
|
||||
@@ -38,7 +38,6 @@ import org.geysermc.api.GeyserApiBase;
|
||||
import org.geysermc.api.connection.Connection;
|
||||
import org.geysermc.floodgate.api.event.skin.SkinApplyEvent.SkinData;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.core.util.Utils;
|
||||
import org.geysermc.floodgate.core.util.WebsocketEventType;
|
||||
import org.java_websocket.client.WebSocketClient;
|
||||
import org.java_websocket.handshake.ServerHandshake;
|
||||
@@ -107,7 +106,7 @@ final class SkinUploadSocket extends WebSocketClient {
|
||||
break;
|
||||
case SKIN_UPLOADED:
|
||||
String xuid = message.get("xuid").getAsString();
|
||||
Connection player = api.connectionByUuid(Utils.getJavaUuid(xuid));
|
||||
Connection player = api.connectionByXuid(xuid);
|
||||
if (player != null) {
|
||||
if (!message.get("success").getAsBoolean()) {
|
||||
logger.info("Failed to upload skin for {} ({})", xuid,
|
||||
|
||||
@@ -25,15 +25,16 @@
|
||||
|
||||
package org.geysermc.floodgate.core.util;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import java.net.URL;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.Getter;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.core.config.FloodgateConfig;
|
||||
@@ -186,7 +187,8 @@ public final class LanguageManager {
|
||||
return true;
|
||||
}
|
||||
|
||||
private String formatNotFound(String key, Object... args) {
|
||||
return key + " " + Joiner.on(", ").join(args);
|
||||
private String formatNotFound(String key, Object... rawArgs) {
|
||||
var args = Arrays.stream(rawArgs).map(Object::toString).collect(Collectors.joining(", "));
|
||||
return key + " " + args;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user