mirror of
https://github.com/GeyserMC/Floodgate.git
synced 2025-12-28 19:19:15 +00:00
Proof-of-concept for Geyser-Floodgate merge
This commit is contained in:
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2022 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.api.player;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@Deprecated
|
||||
public class PropertyKey {
|
||||
/**
|
||||
* Socket Address returns the InetSocketAddress of the Bedrock player
|
||||
*/
|
||||
public static final PropertyKey SOCKET_ADDRESS =
|
||||
new PropertyKey("socket_address", false, false);
|
||||
|
||||
/**
|
||||
* Skin Uploaded returns a SkinData object containing the value and signature of the Skin
|
||||
*/
|
||||
public static final PropertyKey SKIN_UPLOADED =
|
||||
new PropertyKey("skin_uploaded", false, false);
|
||||
|
||||
private final String key;
|
||||
private final boolean changeable;
|
||||
private final boolean removable;
|
||||
|
||||
public PropertyKey(String key, boolean changeable, boolean removable) {
|
||||
this.key = key;
|
||||
this.changeable = changeable;
|
||||
this.removable = removable;
|
||||
}
|
||||
|
||||
public Result isAddAllowed(Object obj) {
|
||||
if (obj instanceof PropertyKey) {
|
||||
PropertyKey propertyKey = (PropertyKey) obj;
|
||||
|
||||
if (key.equals(propertyKey.key)) {
|
||||
if ((propertyKey.changeable == changeable || propertyKey.changeable) &&
|
||||
(propertyKey.removable == removable || propertyKey.removable)) {
|
||||
return Result.ALLOWED;
|
||||
}
|
||||
return Result.INVALID_TAGS;
|
||||
}
|
||||
return Result.NOT_EQUALS;
|
||||
}
|
||||
|
||||
if (obj instanceof String) {
|
||||
if (key.equals(obj)) {
|
||||
if (changeable) {
|
||||
return Result.ALLOWED;
|
||||
}
|
||||
return Result.NOT_ALLOWED;
|
||||
}
|
||||
return Result.INVALID_TAGS;
|
||||
}
|
||||
return Result.NOT_EQUALS;
|
||||
}
|
||||
|
||||
public enum Result {
|
||||
NOT_EQUALS,
|
||||
INVALID_TAGS,
|
||||
NOT_ALLOWED,
|
||||
ALLOWED
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ allprojects {
|
||||
}
|
||||
|
||||
val deployProjects = setOf(
|
||||
projects.api,
|
||||
projects.legacyApi,
|
||||
// for future Floodgate integration + Fabric
|
||||
projects.core,
|
||||
projects.bungee,
|
||||
|
||||
@@ -29,10 +29,10 @@ import com.google.inject.Inject;
|
||||
import com.google.inject.name.Named;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.util.AttributeKey;
|
||||
import org.geysermc.api.connection.Connection;
|
||||
import org.geysermc.floodgate.api.ProxyFloodgateApi;
|
||||
import org.geysermc.floodgate.api.inject.InjectorAddon;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
import org.geysermc.floodgate.config.ProxyFloodgateConfig;
|
||||
import org.geysermc.floodgate.player.FloodgateHandshakeHandler;
|
||||
|
||||
@@ -60,7 +60,7 @@ public class BungeeDataAddon implements InjectorAddon {
|
||||
|
||||
@Inject
|
||||
@Named("playerAttribute")
|
||||
private AttributeKey<FloodgatePlayer> playerAttribute;
|
||||
private AttributeKey<Connection> playerAttribute;
|
||||
|
||||
@Override
|
||||
public void onInject(Channel channel, boolean toServer) {
|
||||
@@ -85,9 +85,9 @@ public class BungeeDataAddon implements InjectorAddon {
|
||||
|
||||
@Override
|
||||
public void onChannelClosed(Channel channel) {
|
||||
FloodgatePlayer player = channel.attr(playerAttribute).get();
|
||||
Connection player = channel.attr(playerAttribute).get();
|
||||
if (player != null && api.setPendingRemove(player)) {
|
||||
logger.translatedInfo("floodgate.ingame.disconnect_name", player.getCorrectUsername());
|
||||
logger.translatedInfo("floodgate.ingame.disconnect_name", player.javaUsername());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,8 +39,8 @@ import net.md_5.bungee.netty.ChannelWrapper;
|
||||
import net.md_5.bungee.netty.HandlerBoss;
|
||||
import net.md_5.bungee.netty.PacketHandler;
|
||||
import net.md_5.bungee.protocol.packet.Handshake;
|
||||
import org.geysermc.api.connection.Connection;
|
||||
import org.geysermc.floodgate.api.ProxyFloodgateApi;
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
import org.geysermc.floodgate.player.FloodgatePlayerImpl;
|
||||
import org.geysermc.floodgate.util.BedrockData;
|
||||
import org.geysermc.floodgate.util.ReflectionUtils;
|
||||
@@ -65,7 +65,7 @@ public class BungeeServerDataHandler extends ChannelOutboundHandlerAdapter {
|
||||
}
|
||||
|
||||
private final ProxyFloodgateApi api;
|
||||
private final AttributeKey<FloodgatePlayer> playerAttribute;
|
||||
private final AttributeKey<Connection> playerAttribute;
|
||||
|
||||
@Override
|
||||
public void write(ChannelHandlerContext ctx, Object packet, ChannelPromise promise) {
|
||||
@@ -83,10 +83,10 @@ public class BungeeServerDataHandler extends ChannelOutboundHandlerAdapter {
|
||||
UserConnection connection = ReflectionUtils.getCastedValue(handler, USER_CONNECTION);
|
||||
ChannelWrapper wrapper = ReflectionUtils.getCastedValue(connection, CHANNEL_WRAPPER);
|
||||
|
||||
FloodgatePlayer player = wrapper.getHandle().attr(playerAttribute).get();
|
||||
Connection player = wrapper.getHandle().attr(playerAttribute).get();
|
||||
|
||||
if (player != null) {
|
||||
BedrockData data = player.as(FloodgatePlayerImpl.class).toBedrockData();
|
||||
BedrockData data = ((FloodgatePlayerImpl) player).toBedrockData();
|
||||
String encryptedData = api.createEncryptedDataString(data);
|
||||
|
||||
Handshake handshake = (Handshake) packet;
|
||||
@@ -105,7 +105,7 @@ public class BungeeServerDataHandler extends ChannelOutboundHandlerAdapter {
|
||||
}
|
||||
|
||||
handshake.setHost(originalAddress + '\0' + encryptedData + remaining);
|
||||
// Bungeecord will add his data after our data
|
||||
// Bungeecord will add its data after our data
|
||||
}
|
||||
|
||||
ctx.pipeline().remove(this);
|
||||
|
||||
@@ -43,9 +43,9 @@ import net.md_5.bungee.connection.InitialHandler;
|
||||
import net.md_5.bungee.event.EventHandler;
|
||||
import net.md_5.bungee.event.EventPriority;
|
||||
import net.md_5.bungee.netty.ChannelWrapper;
|
||||
import org.geysermc.api.connection.Connection;
|
||||
import org.geysermc.floodgate.api.ProxyFloodgateApi;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
import org.geysermc.floodgate.config.ProxyFloodgateConfig;
|
||||
import org.geysermc.floodgate.skin.SkinApplier;
|
||||
import org.geysermc.floodgate.skin.SkinData;
|
||||
@@ -74,7 +74,7 @@ public final class BungeeListener implements Listener {
|
||||
|
||||
@Inject
|
||||
@Named("playerAttribute")
|
||||
private AttributeKey<FloodgatePlayer> playerAttribute;
|
||||
private AttributeKey<Connection> playerAttribute;
|
||||
|
||||
@Inject
|
||||
@Named("kickMessageAttribute")
|
||||
@@ -100,11 +100,11 @@ public final class BungeeListener implements Listener {
|
||||
return;
|
||||
}
|
||||
|
||||
FloodgatePlayer player = channel.attr(playerAttribute).get();
|
||||
Connection player = channel.attr(playerAttribute).get();
|
||||
if (player != null) {
|
||||
connection.setOnlineMode(false);
|
||||
connection.setUniqueId(player.getCorrectUniqueId());
|
||||
ReflectionUtils.setValue(connection, PLAYER_NAME, player.getCorrectUsername());
|
||||
connection.setUniqueId(player.javaUuid());
|
||||
ReflectionUtils.setValue(connection, PLAYER_NAME, player.javaUsername());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,15 +113,15 @@ public final class BungeeListener implements Listener {
|
||||
// if there was another player with the same uuid / name online,
|
||||
// he has been disconnected by now
|
||||
UUID uniqueId = event.getConnection().getUniqueId();
|
||||
FloodgatePlayer player = api.getPlayer(uniqueId);
|
||||
Connection player = api.connectionByUuid(uniqueId);
|
||||
if (player != null) {
|
||||
//todo we should probably move this log message earlier in the process, so that we know
|
||||
// that Floodgate has done its job
|
||||
logger.translatedInfo(
|
||||
"floodgate.ingame.login_name",
|
||||
player.getCorrectUsername(), uniqueId
|
||||
player.javaUsername(), uniqueId
|
||||
);
|
||||
languageManager.loadLocale(player.getLanguageCode());
|
||||
languageManager.loadLocale(player.languageCode());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ public final class BungeeListener implements Listener {
|
||||
public void onPostLogin(PostLoginEvent event) {
|
||||
// To fix the February 2 2022 Mojang authentication changes
|
||||
if (!config.isSendFloodgateData()) {
|
||||
FloodgatePlayer player = api.getPlayer(event.getPlayer().getUniqueId());
|
||||
Connection player = api.connectionByUuid(event.getPlayer().getUniqueId());
|
||||
if (player != null && !player.isLinked() && !skinApplier.hasSkin(player)) {
|
||||
skinApplier.applySkin(player, new SkinData("", ""));
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ import lombok.RequiredArgsConstructor;
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.plugin.Listener;
|
||||
import net.md_5.bungee.api.plugin.Plugin;
|
||||
import org.geysermc.api.GeyserApiBase;
|
||||
import org.geysermc.floodgate.api.FloodgateApi;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.inject.CommonPlatformInjector;
|
||||
@@ -96,7 +97,7 @@ public final class BungeePlatformModule extends AbstractModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public CommandUtil commandUtil(FloodgateApi api, LanguageManager languageManager) {
|
||||
public CommandUtil commandUtil(GeyserApiBase api, LanguageManager languageManager) {
|
||||
return new BungeeCommandUtil(languageManager, plugin.getProxy(), api);
|
||||
}
|
||||
|
||||
|
||||
@@ -40,8 +40,8 @@ import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.connection.InitialHandler;
|
||||
import net.md_5.bungee.connection.LoginResult;
|
||||
import net.md_5.bungee.protocol.Property;
|
||||
import org.geysermc.api.connection.Connection;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
import org.geysermc.floodgate.skin.SkinApplier;
|
||||
import org.geysermc.floodgate.skin.SkinData;
|
||||
import org.geysermc.floodgate.util.ReflectionUtils;
|
||||
@@ -80,8 +80,8 @@ public final class BungeeSkinApplier implements SkinApplier {
|
||||
private final FloodgateLogger logger;
|
||||
|
||||
@Override
|
||||
public void applySkin(FloodgatePlayer uuid, SkinData skinData) {
|
||||
ProxiedPlayer player = ProxyServer.getInstance().getPlayer(uuid.getCorrectUniqueId());
|
||||
public void applySkin(Connection uuid, SkinData skinData) {
|
||||
ProxiedPlayer player = ProxyServer.getInstance().getPlayer(uuid.javaUuid());
|
||||
if (player == null) {
|
||||
return;
|
||||
}
|
||||
@@ -114,8 +114,8 @@ public final class BungeeSkinApplier implements SkinApplier {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSkin(FloodgatePlayer fPlayer) {
|
||||
ProxiedPlayer player = ProxyServer.getInstance().getPlayer(fPlayer.getCorrectUniqueId());
|
||||
public boolean hasSkin(Connection fPlayer) {
|
||||
ProxiedPlayer player = ProxyServer.getInstance().getPlayer(fPlayer.javaUuid());
|
||||
if (player == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.geysermc.api.GeyserApiBase;
|
||||
import org.geysermc.floodgate.api.FloodgateApi;
|
||||
import org.geysermc.floodgate.platform.command.CommandUtil;
|
||||
import org.geysermc.floodgate.player.UserAudience;
|
||||
@@ -41,7 +42,7 @@ public final class BungeeCommandUtil extends CommandUtil {
|
||||
private final ProxyServer server;
|
||||
private UserAudience console;
|
||||
|
||||
public BungeeCommandUtil(LanguageManager manager, ProxyServer server, FloodgateApi api) {
|
||||
public BungeeCommandUtil(LanguageManager manager, ProxyServer server, GeyserApiBase api) {
|
||||
super(manager, api);
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,8 @@ plugins {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(projects.api)
|
||||
api("org.geysermc", "api", "3.0.0-SNAPSHOT")
|
||||
api("org.geysermc", "floodgate-legacy-api", "3.0.0-SNAPSHOT")
|
||||
api("org.geysermc.configutils", "configutils", Versions.configUtilsVersion)
|
||||
|
||||
compileOnly(projects.ap)
|
||||
|
||||
@@ -32,9 +32,12 @@ import com.google.inject.Module;
|
||||
import java.util.UUID;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import org.geysermc.api.Geyser;
|
||||
import org.geysermc.api.GeyserApiBase;
|
||||
import org.geysermc.floodgate.api.FloodgateApi;
|
||||
import org.geysermc.floodgate.api.InstanceHolder;
|
||||
import org.geysermc.floodgate.api.handshake.HandshakeHandlers;
|
||||
import org.geysermc.floodgate.api.impl.FloodgateApiWrapper;
|
||||
import org.geysermc.floodgate.api.inject.PlatformInjector;
|
||||
import org.geysermc.floodgate.api.link.PlayerLink;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
@@ -64,14 +67,15 @@ public abstract class FloodgatePlatform {
|
||||
config = guice.getInstance(FloodgateConfig.class);
|
||||
injector = guice.getInstance(PlatformInjector.class);
|
||||
|
||||
GeyserApiBase api = guice.getInstance(GeyserApiBase.class);
|
||||
InstanceHolder.set(
|
||||
guice.getInstance(FloodgateApi.class),
|
||||
new FloodgateApiWrapper(api),
|
||||
guice.getInstance(PlayerLink.class),
|
||||
injector,
|
||||
guice.getInstance(PacketHandlers.class),
|
||||
guice.getInstance(HandshakeHandlers.class),
|
||||
KEY
|
||||
);
|
||||
Geyser.set(api);
|
||||
|
||||
long endTime = System.currentTimeMillis();
|
||||
guice.getInstance(FloodgateLogger.class)
|
||||
|
||||
@@ -36,7 +36,7 @@ import org.geysermc.floodgate.util.LinkedPlayer;
|
||||
import org.geysermc.floodgate.util.Utils;
|
||||
|
||||
@Getter
|
||||
public class HandshakeDataImpl implements HandshakeData {
|
||||
public class HandshakeDataImpl {
|
||||
private final Channel channel;
|
||||
private final boolean floodgatePlayer;
|
||||
private final BedrockData bedrockData;
|
||||
|
||||
@@ -32,7 +32,7 @@ import org.geysermc.floodgate.api.handshake.HandshakeData;
|
||||
import org.geysermc.floodgate.api.handshake.HandshakeHandler;
|
||||
import org.geysermc.floodgate.api.handshake.HandshakeHandlers;
|
||||
|
||||
public class HandshakeHandlersImpl implements HandshakeHandlers {
|
||||
public class HandshakeHandlersImpl {
|
||||
private final Random random = new Random();
|
||||
private final Int2ObjectMap<HandshakeHandler> handshakeHandlers = new Int2ObjectOpenHashMap<>();
|
||||
|
||||
|
||||
@@ -27,32 +27,30 @@ package org.geysermc.floodgate.api;
|
||||
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.inject.Inject;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.api.GeyserApiBase;
|
||||
import org.geysermc.api.connection.Connection;
|
||||
import org.geysermc.cumulus.form.Form;
|
||||
import org.geysermc.cumulus.form.util.FormBuilder;
|
||||
import org.geysermc.floodgate.api.link.PlayerLink;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
import org.geysermc.floodgate.api.unsafe.Unsafe;
|
||||
import org.geysermc.floodgate.config.FloodgateConfig;
|
||||
import org.geysermc.floodgate.pluginmessage.PluginMessageManager;
|
||||
import org.geysermc.floodgate.pluginmessage.channel.FormChannel;
|
||||
import org.geysermc.floodgate.pluginmessage.channel.TransferChannel;
|
||||
import org.geysermc.floodgate.util.Constants;
|
||||
import org.geysermc.floodgate.util.HttpClient;
|
||||
import org.geysermc.floodgate.util.Utils;
|
||||
|
||||
public class SimpleFloodgateApi implements FloodgateApi {
|
||||
private final Map<UUID, FloodgatePlayer> players = new HashMap<>();
|
||||
private final Cache<UUID, FloodgatePlayer> pendingRemove =
|
||||
public class SimpleFloodgateApi implements GeyserApiBase {
|
||||
private final Map<UUID, Connection> players = new HashMap<>();
|
||||
private final Cache<UUID, Connection> pendingRemove =
|
||||
CacheBuilder.newBuilder()
|
||||
.expireAfterWrite(20, TimeUnit.SECONDS)
|
||||
.build();
|
||||
@@ -63,28 +61,28 @@ public class SimpleFloodgateApi implements FloodgateApi {
|
||||
@Inject private FloodgateLogger logger;
|
||||
|
||||
@Override
|
||||
public String getPlayerPrefix() {
|
||||
public String usernamePrefix() {
|
||||
return config.getUsernamePrefix();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<FloodgatePlayer> getPlayers() {
|
||||
return ImmutableSet.copyOf(players.values());
|
||||
public @NonNull List<? extends Connection> onlineConnections() {
|
||||
return players.values().stream().collect(Collectors.toList()); // TODO guarantee immutable
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPlayerCount() {
|
||||
public int onlineConnectionsCount() {
|
||||
return players.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFloodgatePlayer(UUID uuid) {
|
||||
return getPlayer(uuid) != null;
|
||||
public boolean isBedrockPlayer(@NonNull UUID uuid) {
|
||||
return connectionByUuid(uuid) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FloodgatePlayer getPlayer(UUID uuid) {
|
||||
FloodgatePlayer selfPlayer = players.get(uuid);
|
||||
public @Nullable Connection connectionByUuid(@NonNull UUID uuid) {
|
||||
Connection selfPlayer = players.get(uuid);
|
||||
if (selfPlayer != null) {
|
||||
return selfPlayer;
|
||||
}
|
||||
@@ -96,8 +94,9 @@ public class SimpleFloodgateApi implements FloodgateApi {
|
||||
}
|
||||
|
||||
// make it possible to find player by Java id (linked players)
|
||||
for (FloodgatePlayer player : players.values()) {
|
||||
if (player.getCorrectUniqueId().equals(uuid)) {
|
||||
// TODO still needed?
|
||||
for (Connection player : players.values()) {
|
||||
if (player.javaUuid().equals(uuid)) {
|
||||
return player;
|
||||
}
|
||||
}
|
||||
@@ -106,42 +105,32 @@ public class SimpleFloodgateApi implements FloodgateApi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID createJavaPlayerId(long xuid) {
|
||||
return Utils.getJavaUuid(xuid);
|
||||
public @Nullable Connection connectionByXuid(@NonNull String s) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFloodgateId(UUID uuid) {
|
||||
return uuid.getMostSignificantBits() == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sendForm(UUID uuid, Form form) {
|
||||
public boolean sendForm(@NonNull UUID uuid, @NonNull Form form) {
|
||||
return pluginMessageManager.getChannel(FormChannel.class).sendForm(uuid, form);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sendForm(UUID uuid, FormBuilder<?, ?, ?> formBuilder) {
|
||||
public boolean sendForm(@NonNull UUID uuid, FormBuilder<?, ?, ?> formBuilder) {
|
||||
return sendForm(uuid, formBuilder.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sendForm(UUID uuid, org.geysermc.cumulus.Form<?> form) {
|
||||
return sendForm(uuid, form.newForm());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sendForm(UUID uuid, org.geysermc.cumulus.util.FormBuilder<?, ?> formBuilder) {
|
||||
return sendForm(uuid, formBuilder.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean transferPlayer(UUID uuid, String address, int port) {
|
||||
public boolean transfer(@NonNull UUID uuid, @NonNull String address, int port) {
|
||||
return pluginMessageManager
|
||||
.getChannel(TransferChannel.class)
|
||||
.sendTransfer(uuid, address, port);
|
||||
}
|
||||
|
||||
/*
|
||||
@Override
|
||||
public CompletableFuture<Long> getXuidFor(String gamertag) {
|
||||
if (gamertag == null || gamertag.isEmpty() || gamertag.length() > 16) {
|
||||
@@ -184,19 +173,21 @@ public class SimpleFloodgateApi implements FloodgateApi {
|
||||
" Caller: " + callerClass);
|
||||
return new UnsafeFloodgateApi(pluginMessageManager);
|
||||
}
|
||||
*/
|
||||
|
||||
public FloodgatePlayer addPlayer(FloodgatePlayer player) {
|
||||
public Connection addPlayer(Connection player) {
|
||||
// Bedrock players are always stored by their xuid
|
||||
return players.put(player.getJavaUniqueId(), player);
|
||||
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(FloodgatePlayer player) {
|
||||
pendingRemove.put(player.getJavaUniqueId(), player);
|
||||
return players.remove(player.getJavaUniqueId(), player);
|
||||
public boolean setPendingRemove(Connection player) {
|
||||
pendingRemove.put(player.javaUuid(), player);
|
||||
return players.remove(player.javaUuid(), player);
|
||||
}
|
||||
|
||||
public void playerRemoved(UUID correctUuid) {
|
||||
@@ -206,18 +197,22 @@ public class SimpleFloodgateApi implements FloodgateApi {
|
||||
pendingRemove.invalidate(correctUuid);
|
||||
return;
|
||||
}
|
||||
FloodgatePlayer linkedPlayer = getPendingRemovePlayer(correctUuid);
|
||||
Connection linkedPlayer = getPendingRemovePlayer(correctUuid);
|
||||
if (linkedPlayer != null) {
|
||||
pendingRemove.invalidate(linkedPlayer.getJavaUniqueId());
|
||||
pendingRemove.invalidate(linkedPlayer.javaUuid());
|
||||
}
|
||||
}
|
||||
|
||||
private FloodgatePlayer getPendingRemovePlayer(UUID correctUuid) {
|
||||
for (FloodgatePlayer player : pendingRemove.asMap().values()) {
|
||||
if (player.getCorrectUniqueId().equals(correctUuid)) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ import com.google.inject.Inject;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.geysermc.floodgate.api.FloodgateApi;
|
||||
import org.geysermc.floodgate.api.SimpleFloodgateApi;
|
||||
import org.geysermc.floodgate.api.link.LinkRequestResult;
|
||||
import org.geysermc.floodgate.api.link.PlayerLink;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
@@ -52,7 +53,7 @@ import org.geysermc.floodgate.util.Constants;
|
||||
|
||||
@NoArgsConstructor
|
||||
public final class LinkAccountCommand implements FloodgateCommand {
|
||||
@Inject private FloodgateApi api;
|
||||
@Inject private SimpleFloodgateApi api;
|
||||
@Inject private FloodgateLogger logger;
|
||||
|
||||
@Override
|
||||
@@ -95,7 +96,7 @@ public final class LinkAccountCommand implements FloodgateCommand {
|
||||
String targetName = targetUser.username();
|
||||
|
||||
// when the player is a Bedrock player
|
||||
if (api.isFloodgatePlayer(sender.uuid())) {
|
||||
if (api.isBedrockPlayer(sender.uuid())) {
|
||||
if (!context.contains("code")) {
|
||||
sender.sendMessage(Message.BEDROCK_USAGE);
|
||||
return;
|
||||
|
||||
@@ -28,6 +28,7 @@ package org.geysermc.floodgate.command;
|
||||
import cloud.commandframework.Command;
|
||||
import cloud.commandframework.CommandManager;
|
||||
import cloud.commandframework.context.CommandContext;
|
||||
import org.geysermc.api.Geyser;
|
||||
import org.geysermc.floodgate.api.FloodgateApi;
|
||||
import org.geysermc.floodgate.config.FloodgateConfig;
|
||||
import org.geysermc.floodgate.platform.command.FloodgateCommand;
|
||||
@@ -45,7 +46,7 @@ public class TestCommand implements FloodgateCommand {
|
||||
|
||||
@Override
|
||||
public void execute(CommandContext<UserAudience> context) {
|
||||
int players = FloodgateApi.getInstance().getPlayers().size();
|
||||
int players = Geyser.api().onlineConnectionsCount();
|
||||
context.getSender().sendMessage(String.valueOf(players));
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ import com.google.inject.Inject;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.geysermc.floodgate.api.FloodgateApi;
|
||||
import org.geysermc.floodgate.api.SimpleFloodgateApi;
|
||||
import org.geysermc.floodgate.api.link.PlayerLink;
|
||||
import org.geysermc.floodgate.config.FloodgateConfig;
|
||||
import org.geysermc.floodgate.link.GlobalPlayerLinking;
|
||||
@@ -47,7 +48,7 @@ import org.geysermc.floodgate.command.util.Permission;
|
||||
|
||||
@NoArgsConstructor
|
||||
public final class UnlinkAccountCommand implements FloodgateCommand {
|
||||
@Inject private FloodgateApi api;
|
||||
@Inject private SimpleFloodgateApi api;
|
||||
|
||||
@Override
|
||||
public Command<UserAudience> buildCommand(CommandManager<UserAudience> commandManager) {
|
||||
|
||||
@@ -86,7 +86,7 @@ public class WhitelistCommand implements FloodgateCommand {
|
||||
}
|
||||
|
||||
if (uuid != null) {
|
||||
if (!FloodgateApi.getInstance().isFloodgateId(uuid)) {
|
||||
if (uuid.getMostSignificantBits() != 0) { // TODO
|
||||
sender.sendMessage(Message.INVALID_USERNAME);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -64,9 +64,12 @@ public class FloodgateConfig implements GenericPostInitializeCallback<ConfigLoad
|
||||
public CallbackResult postInitialize(ConfigLoader loader) {
|
||||
Path keyPath = loader.getDataDirectory().resolve(getKeyFileName());
|
||||
|
||||
// don't assume that the key always exists with the existence of a config
|
||||
if (!Files.exists(keyPath)) {
|
||||
loader.generateKey(keyPath);
|
||||
// TODO improve message and also link to article about corrupted keys/WinSCP/FTP
|
||||
// Like, where is key.pem?
|
||||
// TODO don't be so noisy with error. It makes it hard to understand what the error is.
|
||||
return CallbackResult.failed("Floodgate requires a key file! " +
|
||||
"Copy your key file from Geyser (key.pem) and paste it into " + keyPath);
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
@@ -39,16 +39,16 @@ import java.nio.file.Path;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.geysermc.api.GeyserApiBase;
|
||||
import org.geysermc.api.connection.Connection;
|
||||
import org.geysermc.event.PostOrder;
|
||||
import org.geysermc.floodgate.addon.data.HandshakeHandlersImpl;
|
||||
import org.geysermc.floodgate.api.FloodgateApi;
|
||||
import org.geysermc.floodgate.api.SimpleFloodgateApi;
|
||||
import org.geysermc.floodgate.api.handshake.HandshakeHandlers;
|
||||
import org.geysermc.floodgate.api.inject.PlatformInjector;
|
||||
import org.geysermc.floodgate.api.link.PlayerLink;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.api.packet.PacketHandlers;
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
import org.geysermc.floodgate.config.ConfigLoader;
|
||||
import org.geysermc.floodgate.config.FloodgateConfig;
|
||||
import org.geysermc.floodgate.crypto.AesCipher;
|
||||
@@ -91,7 +91,7 @@ public class CommonModule extends AbstractModule {
|
||||
|
||||
bind(HttpClient.class).in(Singleton.class);
|
||||
|
||||
bind(FloodgateApi.class).to(SimpleFloodgateApi.class);
|
||||
bind(GeyserApiBase.class).to(SimpleFloodgateApi.class);
|
||||
bind(PlatformInjector.class).to(CommonPlatformInjector.class);
|
||||
|
||||
bind(HandshakeHandlers.class).to(HandshakeHandlersImpl.class);
|
||||
@@ -151,7 +151,7 @@ public class CommonModule extends AbstractModule {
|
||||
FloodgateCipher cipher,
|
||||
FloodgateConfig config,
|
||||
SkinUploadManager skinUploadManager,
|
||||
@Named("playerAttribute") AttributeKey<FloodgatePlayer> playerAttribute,
|
||||
@Named("playerAttribute") AttributeKey<Connection> playerAttribute,
|
||||
FloodgateLogger logger) {
|
||||
|
||||
return new FloodgateHandshakeHandler(handshakeHandlers, api, cipher, config,
|
||||
@@ -167,7 +167,7 @@ public class CommonModule extends AbstractModule {
|
||||
@Provides
|
||||
@Singleton
|
||||
public SkinUploadManager skinUploadManager(
|
||||
FloodgateApi api,
|
||||
GeyserApiBase api,
|
||||
SkinApplier skinApplier,
|
||||
FloodgateLogger logger) {
|
||||
return new SkinUploadManager(api, skinApplier, logger);
|
||||
@@ -197,7 +197,7 @@ public class CommonModule extends AbstractModule {
|
||||
@Provides
|
||||
@Singleton
|
||||
@Named("playerAttribute")
|
||||
public AttributeKey<FloodgatePlayer> playerAttribute() {
|
||||
public AttributeKey<Connection> playerAttribute() {
|
||||
return AttributeKey.valueOf("floodgate-player");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ import lombok.AccessLevel;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.api.GeyserApiBase;
|
||||
import org.geysermc.floodgate.api.FloodgateApi;
|
||||
import org.geysermc.floodgate.platform.util.PlayerType;
|
||||
import org.geysermc.floodgate.player.UserAudience;
|
||||
@@ -51,7 +52,7 @@ import org.geysermc.floodgate.util.Utils;
|
||||
@RequiredArgsConstructor(access = AccessLevel.PROTECTED)
|
||||
public abstract class CommandUtil {
|
||||
protected final LanguageManager manager;
|
||||
protected final FloodgateApi api;
|
||||
protected final GeyserApiBase api;
|
||||
|
||||
public abstract @NonNull UserAudience getUserAudience(@NonNull Object source);
|
||||
|
||||
@@ -94,14 +95,14 @@ public abstract class CommandUtil {
|
||||
break;
|
||||
case ONLY_JAVA:
|
||||
for (Object player : players) {
|
||||
if (!api.isFloodgatePlayer(getUuidFromSource(player))) {
|
||||
if (!api.isBedrockPlayer(getUuidFromSource(player))) {
|
||||
usernames.add(getUsernameFromSource(player));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ONLY_BEDROCK:
|
||||
for (Object player : players) {
|
||||
if (api.isFloodgatePlayer(getUuidFromSource(player))) {
|
||||
if (api.isBedrockPlayer(getUuidFromSource(player))) {
|
||||
usernames.add(getUsernameFromSource(player));
|
||||
}
|
||||
}
|
||||
@@ -133,7 +134,7 @@ public abstract class CommandUtil {
|
||||
if (filter == ALL_PLAYERS || player instanceof String || player instanceof UUID) {
|
||||
return player;
|
||||
}
|
||||
return (filter == ONLY_BEDROCK) == api.isFloodgatePlayer(getUuidFromSource(player))
|
||||
return (filter == ONLY_BEDROCK) == api.isBedrockPlayer(getUuidFromSource(player))
|
||||
? player
|
||||
: fallback;
|
||||
}
|
||||
|
||||
@@ -41,13 +41,12 @@ import lombok.AccessLevel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import org.geysermc.api.connection.Connection;
|
||||
import org.geysermc.floodgate.addon.data.HandshakeDataImpl;
|
||||
import org.geysermc.floodgate.addon.data.HandshakeHandlersImpl;
|
||||
import org.geysermc.floodgate.api.SimpleFloodgateApi;
|
||||
import org.geysermc.floodgate.api.handshake.HandshakeData;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
import org.geysermc.floodgate.api.player.PropertyKey;
|
||||
import org.geysermc.floodgate.config.FloodgateConfig;
|
||||
import org.geysermc.floodgate.crypto.FloodgateCipher;
|
||||
import org.geysermc.floodgate.skin.SkinUploadManager;
|
||||
@@ -62,7 +61,7 @@ public final class FloodgateHandshakeHandler {
|
||||
private final FloodgateCipher cipher;
|
||||
private final FloodgateConfig config;
|
||||
private final SkinUploadManager skinUploadManager;
|
||||
private final AttributeKey<FloodgatePlayer> playerAttribute;
|
||||
private final AttributeKey<Connection> playerAttribute;
|
||||
private final FloodgateLogger logger;
|
||||
|
||||
public FloodgateHandshakeHandler(
|
||||
@@ -71,7 +70,7 @@ public final class FloodgateHandshakeHandler {
|
||||
FloodgateCipher cipher,
|
||||
FloodgateConfig config,
|
||||
SkinUploadManager skinUploadManager,
|
||||
AttributeKey<FloodgatePlayer> playerAttribute,
|
||||
AttributeKey<Connection> playerAttribute,
|
||||
FloodgateLogger logger) {
|
||||
|
||||
this.handshakeHandlers = handshakeHandlers;
|
||||
@@ -206,7 +205,7 @@ public final class FloodgateHandshakeHandler {
|
||||
LinkedPlayer linkedPlayer) {
|
||||
|
||||
try {
|
||||
HandshakeData handshakeData = new HandshakeDataImpl(
|
||||
HandshakeDataImpl handshakeData = new HandshakeDataImpl(
|
||||
channel, true, bedrockData.clone(), config,
|
||||
linkedPlayer != null ? linkedPlayer.clone() : null, hostname);
|
||||
|
||||
@@ -221,16 +220,14 @@ public final class FloodgateHandshakeHandler {
|
||||
bedrockData.getVerifyCode());
|
||||
}
|
||||
|
||||
FloodgatePlayer player = FloodgatePlayerImpl.from(bedrockData, handshakeData);
|
||||
int port = ((InetSocketAddress) channel.remoteAddress()).getPort();
|
||||
|
||||
Connection player = FloodgatePlayerImpl.from(bedrockData, handshakeData, port);
|
||||
|
||||
api.addPlayer(player);
|
||||
|
||||
channel.attr(playerAttribute).set(player);
|
||||
|
||||
int port = ((InetSocketAddress) channel.remoteAddress()).getPort();
|
||||
InetSocketAddress socketAddress = new InetSocketAddress(handshakeData.getIp(), port);
|
||||
player.addProperty(PropertyKey.SOCKET_ADDRESS, socketAddress);
|
||||
|
||||
return new HandshakeResult(ResultType.SUCCESS, handshakeData, bedrockData, player);
|
||||
} catch (Exception exception) {
|
||||
exception.printStackTrace();
|
||||
@@ -244,7 +241,7 @@ public final class FloodgateHandshakeHandler {
|
||||
BedrockData bedrockData,
|
||||
String hostname) {
|
||||
|
||||
HandshakeData handshakeData = new HandshakeDataImpl(channel, bedrockData != null,
|
||||
HandshakeInjectedData handshakeData = new HandshakeDataImpl(channel, bedrockData != null,
|
||||
bedrockData, config, null, hostname);
|
||||
handshakeHandlers.callHandshakeHandlers(handshakeData);
|
||||
|
||||
@@ -279,13 +276,13 @@ public final class FloodgateHandshakeHandler {
|
||||
@Getter
|
||||
public static class HandshakeResult extends IllegalStateException {
|
||||
private final ResultType resultType;
|
||||
private final HandshakeData handshakeData;
|
||||
private final HandshakeInjectedData handshakeData;
|
||||
private final BedrockData bedrockData;
|
||||
private final FloodgatePlayer floodgatePlayer;
|
||||
private final Connection floodgatePlayer;
|
||||
|
||||
public InetSocketAddress getNewIp(Channel channel) {
|
||||
if (floodgatePlayer != null) {
|
||||
return floodgatePlayer.getProperty(PropertyKey.SOCKET_ADDRESS);
|
||||
return floodgatePlayer.socketAddress();
|
||||
}
|
||||
if (handshakeData.getIp() != null) {
|
||||
int port = ((InetSocketAddress) channel.remoteAddress()).getPort();
|
||||
|
||||
@@ -25,78 +25,108 @@
|
||||
|
||||
package org.geysermc.floodgate.player;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.UUID;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.Builder;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.geysermc.floodgate.api.FloodgateApi;
|
||||
import org.geysermc.floodgate.api.InstanceHolder;
|
||||
import org.geysermc.floodgate.api.ProxyFloodgateApi;
|
||||
import org.geysermc.floodgate.api.handshake.HandshakeData;
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
import org.geysermc.floodgate.api.player.PropertyKey;
|
||||
import org.geysermc.floodgate.api.player.PropertyKey.Result;
|
||||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.common.value.qual.IntRange;
|
||||
import org.geysermc.api.Geyser;
|
||||
import org.geysermc.api.connection.Connection;
|
||||
import org.geysermc.api.util.BedrockPlatform;
|
||||
import org.geysermc.api.util.InputMode;
|
||||
import org.geysermc.api.util.UiProfile;
|
||||
import org.geysermc.cumulus.form.Form;
|
||||
import org.geysermc.cumulus.form.util.FormBuilder;
|
||||
import org.geysermc.floodgate.addon.data.HandshakeDataImpl;
|
||||
import org.geysermc.floodgate.util.BedrockData;
|
||||
import org.geysermc.floodgate.util.DeviceOs;
|
||||
import org.geysermc.floodgate.util.InputMode;
|
||||
import org.geysermc.floodgate.util.LinkedPlayer;
|
||||
import org.geysermc.floodgate.util.UiProfile;
|
||||
import org.geysermc.floodgate.util.Utils;
|
||||
|
||||
@Getter
|
||||
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
@SuppressWarnings("unchecked")
|
||||
public final class FloodgatePlayerImpl implements FloodgatePlayer {
|
||||
@Builder
|
||||
public final class FloodgatePlayerImpl implements Connection {
|
||||
private final String version;
|
||||
private final String username;
|
||||
private final String javaUsername;
|
||||
private final UUID javaUniqueId;
|
||||
private final String xuid;
|
||||
private final DeviceOs deviceOs;
|
||||
private final BedrockPlatform deviceOs;
|
||||
private final String languageCode;
|
||||
private final UiProfile uiProfile;
|
||||
private final InputMode inputMode;
|
||||
private final String ip;
|
||||
private final boolean fromProxy;
|
||||
private final boolean proxy; // if current platform is a proxy
|
||||
private final LinkedPlayer linkedPlayer;
|
||||
|
||||
private final int subscribeId;
|
||||
private final String verifyCode;
|
||||
|
||||
@Getter(AccessLevel.PRIVATE)
|
||||
private Map<PropertyKey, Object> propertyKeyToValue;
|
||||
@Getter(AccessLevel.PRIVATE)
|
||||
private Map<String, PropertyKey> stringToPropertyKey;
|
||||
|
||||
static FloodgatePlayerImpl from(BedrockData data, HandshakeData handshakeData) {
|
||||
FloodgateApi api = InstanceHolder.getApi();
|
||||
private final InetSocketAddress socketAddress;
|
||||
|
||||
static FloodgatePlayerImpl from(BedrockData data, HandshakeDataImpl handshakeData, int port) {
|
||||
UUID javaUniqueId = Utils.getJavaUuid(data.getXuid());
|
||||
|
||||
DeviceOs deviceOs = DeviceOs.fromId(data.getDeviceOs());
|
||||
BedrockPlatform deviceOs = BedrockPlatform.fromId(data.getDeviceOs());
|
||||
UiProfile uiProfile = UiProfile.fromId(data.getUiProfile());
|
||||
InputMode inputMode = InputMode.fromId(data.getInputMode());
|
||||
|
||||
LinkedPlayer linkedPlayer = handshakeData.getLinkedPlayer();
|
||||
|
||||
InetSocketAddress socketAddress = new InetSocketAddress(data.getIp(), port);
|
||||
|
||||
return new FloodgatePlayerImpl(
|
||||
data.getVersion(), data.getUsername(), handshakeData.getJavaUsername(),
|
||||
javaUniqueId, data.getXuid(), deviceOs, data.getLanguageCode(), uiProfile,
|
||||
inputMode, data.getIp(), data.isFromProxy(), api instanceof ProxyFloodgateApi,
|
||||
linkedPlayer, data.getSubscribeId(), data.getVerifyCode());
|
||||
inputMode, data.getIp(), data.isFromProxy(),
|
||||
linkedPlayer, data.getSubscribeId(), data.getVerifyCode(), socketAddress);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getCorrectUniqueId() {
|
||||
public @NonNull String bedrockUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @MonotonicNonNull String javaUsername() {
|
||||
return linkedPlayer != null ? linkedPlayer.getJavaUsername() : javaUsername;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @MonotonicNonNull UUID javaUuid() {
|
||||
return linkedPlayer != null ? linkedPlayer.getJavaUniqueId() : javaUniqueId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCorrectUsername() {
|
||||
return linkedPlayer != null ? linkedPlayer.getJavaUsername() : javaUsername;
|
||||
public @NonNull String xuid() {
|
||||
return xuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull String version() {
|
||||
return version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull BedrockPlatform platform() {
|
||||
return deviceOs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull String languageCode() {
|
||||
return languageCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull UiProfile uiProfile() {
|
||||
return uiProfile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull InputMode inputMode() {
|
||||
return inputMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -104,124 +134,29 @@ public final class FloodgatePlayerImpl implements FloodgatePlayer {
|
||||
return linkedPlayer != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sendForm(@NonNull Form form) {
|
||||
return Geyser.api().sendForm(javaUuid(), form);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sendForm(@NonNull FormBuilder<?, ?, ?> formBuilder) {
|
||||
return Geyser.api().sendForm(javaUuid(), formBuilder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean transfer(@NonNull String address, @IntRange(from = 0L, to = 65535L) int port) {
|
||||
return Geyser.api().transfer(javaUuid(), address, port);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetSocketAddress socketAddress() {
|
||||
return socketAddress;
|
||||
}
|
||||
|
||||
public BedrockData toBedrockData() {
|
||||
return BedrockData.of(version, username, xuid, deviceOs.ordinal(), languageCode,
|
||||
uiProfile.ordinal(), inputMode.ordinal(), ip, linkedPlayer, proxy, subscribeId,
|
||||
verifyCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasProperty(PropertyKey key) {
|
||||
if (propertyKeyToValue == null) {
|
||||
return false;
|
||||
}
|
||||
return propertyKeyToValue.get(key) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasProperty(String key) {
|
||||
if (stringToPropertyKey == null) {
|
||||
return false;
|
||||
}
|
||||
return hasProperty(stringToPropertyKey.get(key));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getProperty(PropertyKey key) {
|
||||
if (propertyKeyToValue == null) {
|
||||
return null;
|
||||
}
|
||||
return (T) propertyKeyToValue.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getProperty(String key) {
|
||||
if (stringToPropertyKey == null) {
|
||||
return null;
|
||||
}
|
||||
return getProperty(stringToPropertyKey.get(key));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T removeProperty(String key) {
|
||||
if (stringToPropertyKey == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
PropertyKey propertyKey = stringToPropertyKey.get(key);
|
||||
|
||||
if (propertyKey == null || !propertyKey.isRemovable()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (T) propertyKeyToValue.remove(propertyKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T removeProperty(PropertyKey key) {
|
||||
if (stringToPropertyKey == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
PropertyKey propertyKey = stringToPropertyKey.get(key.getKey());
|
||||
|
||||
if (propertyKey == null || !propertyKey.equals(key) || !propertyKey.isRemovable()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
stringToPropertyKey.remove(key.getKey());
|
||||
|
||||
return (T) propertyKeyToValue.remove(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T addProperty(PropertyKey key, Object value) {
|
||||
if (stringToPropertyKey == null) {
|
||||
stringToPropertyKey = new HashMap<>();
|
||||
propertyKeyToValue = new HashMap<>();
|
||||
|
||||
stringToPropertyKey.put(key.getKey(), key);
|
||||
propertyKeyToValue.put(key, value);
|
||||
return null;
|
||||
}
|
||||
|
||||
PropertyKey propertyKey = stringToPropertyKey.get(key.getKey());
|
||||
|
||||
if (propertyKey != null && propertyKey.isAddAllowed(key) == Result.ALLOWED) {
|
||||
stringToPropertyKey.put(key.getKey(), key);
|
||||
return (T) propertyKeyToValue.put(key, value);
|
||||
}
|
||||
|
||||
return (T) stringToPropertyKey.computeIfAbsent(key.getKey(), (keyString) -> {
|
||||
propertyKeyToValue.put(key, value);
|
||||
return key;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T addProperty(String key, Object value) {
|
||||
PropertyKey propertyKey = new PropertyKey(key, true, true);
|
||||
|
||||
if (stringToPropertyKey == null) {
|
||||
stringToPropertyKey = new HashMap<>();
|
||||
propertyKeyToValue = new HashMap<>();
|
||||
|
||||
stringToPropertyKey.put(key, propertyKey);
|
||||
propertyKeyToValue.put(propertyKey, value);
|
||||
return null;
|
||||
}
|
||||
|
||||
PropertyKey currentPropertyKey = stringToPropertyKey.get(key);
|
||||
|
||||
// key is always changeable if it passes this if statement
|
||||
if (currentPropertyKey != null && currentPropertyKey.isAddAllowed(key) == Result.ALLOWED) {
|
||||
stringToPropertyKey.put(key, propertyKey);
|
||||
return (T) propertyKeyToValue.put(propertyKey, value);
|
||||
}
|
||||
|
||||
return (T) stringToPropertyKey.computeIfAbsent(key, (keyString) -> {
|
||||
propertyKeyToValue.put(propertyKey, value);
|
||||
return propertyKey;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2022 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.player;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.UUID;
|
||||
import org.geysermc.api.connection.Connection;
|
||||
|
||||
public final class HandshakeInjectedData {
|
||||
// TIM I PROMISE THIS IS JUST AN IDEA
|
||||
// public static Connection read() {
|
||||
// FloodgatePlayerImpl.FloodgatePlayerImplBuilder builder = FloodgatePlayerImpl.builder();
|
||||
//
|
||||
// }
|
||||
//
|
||||
// public static String write(Connection connection) {
|
||||
// ByteBuf buf = Unpooled.buffer();
|
||||
// writeString(connection.version(), buf);
|
||||
// writeString(connection.bedrockUsername(), buf);
|
||||
// writeString(connection.xuid(), buf);
|
||||
// writeVarInt(connection.platform().ordinal(), buf);
|
||||
// writeString(connection.languageCode(), buf);
|
||||
// writeVarInt(connection.uiProfile().ordinal(), buf);
|
||||
// writeVarInt(connection.inputMode().ordinal(), buf);
|
||||
// InetSocketAddress address = (InetSocketAddress) connection.socketAddress();
|
||||
// writeString(address.getHostString(), buf); // TODO
|
||||
// buf.writeShort(address.getPort());
|
||||
// buf.writeBoolean(connection.isLinked());
|
||||
// if (connection.isLinked()) {
|
||||
// writeString(connection.javaUsername(), buf);
|
||||
// UUID uuid = connection.javaUuid();
|
||||
// buf.writeLong(uuid.getMostSignificantBits());
|
||||
// buf.writeLong(uuid.getLeastSignificantBits());
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private static int readVarInt(ByteBuf buf) {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// private static void writeVarInt(int i, ByteBuf buf) {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// private static String readString(ByteBuf buf) {
|
||||
// byte[] bytes = new byte[readVarInt(buf)];
|
||||
// buf.readBytes(bytes);
|
||||
// return new String(bytes, StandardCharsets.UTF_8);
|
||||
// }
|
||||
//
|
||||
// private static void writeString(String s, ByteBuf buf) {
|
||||
// byte[] bytes = s.getBytes(StandardCharsets.UTF_8);
|
||||
// writeVarInt(bytes.length, buf);
|
||||
// buf.writeBytes(bytes);
|
||||
// }
|
||||
}
|
||||
@@ -29,9 +29,8 @@ import com.google.gson.JsonObject;
|
||||
import com.google.inject.Inject;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.UUID;
|
||||
import org.geysermc.floodgate.api.FloodgateApi;
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
import org.geysermc.floodgate.api.player.PropertyKey;
|
||||
import org.geysermc.api.GeyserApiBase;
|
||||
import org.geysermc.api.connection.Connection;
|
||||
import org.geysermc.floodgate.config.FloodgateConfig;
|
||||
import org.geysermc.floodgate.config.ProxyFloodgateConfig;
|
||||
import org.geysermc.floodgate.pluginmessage.PluginMessageChannel;
|
||||
@@ -39,7 +38,7 @@ import org.geysermc.floodgate.skin.SkinApplier;
|
||||
import org.geysermc.floodgate.skin.SkinData;
|
||||
|
||||
public class SkinChannel implements PluginMessageChannel {
|
||||
@Inject private FloodgateApi api;
|
||||
@Inject private GeyserApiBase api;
|
||||
@Inject private FloodgateConfig config;
|
||||
@Inject private SkinApplier skinApplier;
|
||||
|
||||
@@ -76,8 +75,8 @@ public class SkinChannel implements PluginMessageChannel {
|
||||
|
||||
@Override
|
||||
public Result handleServerCall(byte[] data, UUID playerUuid, String playerUsername) {
|
||||
FloodgatePlayer floodgatePlayer = api.getPlayer(playerUuid);
|
||||
if (floodgatePlayer == null) {
|
||||
Connection connection = api.connectionByUuid(playerUuid);
|
||||
if (connection == null) {
|
||||
return Result.kick("Player sent skins data for a non-Floodgate player");
|
||||
}
|
||||
|
||||
@@ -89,7 +88,7 @@ public class SkinChannel implements PluginMessageChannel {
|
||||
return Result.kick("Got invalid skin data");
|
||||
}
|
||||
|
||||
if (floodgatePlayer.isLinked() || skinApplier.hasSkin(floodgatePlayer)) {
|
||||
if (connection.isLinked() || skinApplier.hasSkin(connection)) {
|
||||
return Result.handled();
|
||||
}
|
||||
|
||||
@@ -102,8 +101,7 @@ public class SkinChannel implements PluginMessageChannel {
|
||||
|
||||
SkinData skinData = new SkinData(value, signature);
|
||||
|
||||
floodgatePlayer.addProperty(PropertyKey.SKIN_UPLOADED, skinData);
|
||||
skinApplier.applySkin(floodgatePlayer, skinData);
|
||||
skinApplier.applySkin(connection, skinData);
|
||||
|
||||
return Result.handled();
|
||||
}
|
||||
|
||||
@@ -25,23 +25,23 @@
|
||||
|
||||
package org.geysermc.floodgate.skin;
|
||||
|
||||
import org.geysermc.api.connection.Connection;
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
|
||||
public interface SkinApplier {
|
||||
/**
|
||||
* Apply a skin to a {@link FloodgatePlayer player}
|
||||
*
|
||||
* @param floodgatePlayer player to apply skin to
|
||||
* @param connection player to apply skin to
|
||||
* @param skinData data for skin to apply to player
|
||||
*/
|
||||
void applySkin(FloodgatePlayer floodgatePlayer, SkinData skinData);
|
||||
void applySkin(Connection connection, SkinData skinData);
|
||||
|
||||
/**
|
||||
* Check if a {@link FloodgatePlayer player} currently
|
||||
* has a skin applied.
|
||||
*
|
||||
* @param floodgatePlayer player to check skin of
|
||||
* @param connection player to check skin of
|
||||
* @return if player has a skin
|
||||
*/
|
||||
boolean hasSkin(FloodgatePlayer floodgatePlayer);
|
||||
boolean hasSkin(Connection connection);
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.geysermc.api.GeyserApiBase;
|
||||
import org.geysermc.floodgate.api.FloodgateApi;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
|
||||
@@ -37,7 +38,7 @@ public final class SkinUploadManager {
|
||||
private final Int2ObjectMap<SkinUploadSocket> connections =
|
||||
Int2ObjectMaps.synchronize(new Int2ObjectOpenHashMap<>());
|
||||
|
||||
private final FloodgateApi api;
|
||||
private final GeyserApiBase api;
|
||||
private final SkinApplier applier;
|
||||
private final FloodgateLogger logger;
|
||||
|
||||
|
||||
@@ -34,10 +34,9 @@ import java.net.ConnectException;
|
||||
import java.net.URI;
|
||||
import javax.net.ssl.SSLException;
|
||||
import lombok.Getter;
|
||||
import org.geysermc.floodgate.api.FloodgateApi;
|
||||
import org.geysermc.api.GeyserApiBase;
|
||||
import org.geysermc.api.connection.Connection;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
import org.geysermc.floodgate.api.player.PropertyKey;
|
||||
import org.geysermc.floodgate.util.Utils;
|
||||
import org.geysermc.floodgate.util.WebsocketEventType;
|
||||
import org.java_websocket.client.WebSocketClient;
|
||||
@@ -47,7 +46,7 @@ final class SkinUploadSocket extends WebSocketClient {
|
||||
private static final Gson gson = new Gson();
|
||||
|
||||
private final SkinUploadManager uploadManager;
|
||||
private final FloodgateApi api;
|
||||
private final GeyserApiBase api;
|
||||
private final SkinApplier applier;
|
||||
private final FloodgateLogger logger;
|
||||
|
||||
@@ -59,7 +58,7 @@ final class SkinUploadSocket extends WebSocketClient {
|
||||
int id,
|
||||
String verifyCode,
|
||||
SkinUploadManager uploadManager,
|
||||
FloodgateApi api,
|
||||
GeyserApiBase api,
|
||||
SkinApplier applier,
|
||||
FloodgateLogger logger) {
|
||||
|
||||
@@ -107,16 +106,15 @@ final class SkinUploadSocket extends WebSocketClient {
|
||||
break;
|
||||
case SKIN_UPLOADED:
|
||||
String xuid = message.get("xuid").getAsString();
|
||||
FloodgatePlayer player = api.getPlayer(Utils.getJavaUuid(xuid));
|
||||
Connection player = api.connectionByUuid(Utils.getJavaUuid(xuid));
|
||||
if (player != null) {
|
||||
if (!message.get("success").getAsBoolean()) {
|
||||
logger.info("Failed to upload skin for {} ({})", xuid,
|
||||
player.getCorrectUsername());
|
||||
player.javaUsername());
|
||||
return;
|
||||
}
|
||||
if (!player.isLinked() && !applier.hasSkin(player)) {
|
||||
SkinData skinData = SkinData.from(message.getAsJsonObject("data"));
|
||||
player.addProperty(PropertyKey.SKIN_UPLOADED, skinData);
|
||||
applier.applySkin(player, skinData);
|
||||
}
|
||||
}
|
||||
|
||||
112
core/src/main/java/org/geysermc/floodgate/util/BedrockData.java
Normal file
112
core/src/main/java/org/geysermc/floodgate/util/BedrockData.java
Normal file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2022 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/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.floodgate.util;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
/**
|
||||
* This class contains the raw data send by Geyser to Floodgate or from Floodgate to Floodgate. This
|
||||
* class is only used internally, and you should look at FloodgatePlayer instead (FloodgatePlayer is
|
||||
* present in the API module of the Floodgate repo)
|
||||
*/
|
||||
@Getter
|
||||
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public final class BedrockData implements Cloneable {
|
||||
public static final int EXPECTED_LENGTH = 12;
|
||||
|
||||
private final String version;
|
||||
private final String username;
|
||||
private final String xuid;
|
||||
private final int deviceOs;
|
||||
private final String languageCode;
|
||||
private final int uiProfile;
|
||||
private final int inputMode;
|
||||
private final String ip;
|
||||
private final LinkedPlayer linkedPlayer;
|
||||
private final boolean fromProxy;
|
||||
|
||||
private final int subscribeId;
|
||||
private final String verifyCode;
|
||||
|
||||
private final int dataLength;
|
||||
|
||||
public static BedrockData of(
|
||||
String version, String username, String xuid, int deviceOs,
|
||||
String languageCode, int uiProfile, int inputMode, String ip,
|
||||
LinkedPlayer linkedPlayer, boolean fromProxy, int subscribeId,
|
||||
String verifyCode) {
|
||||
return new BedrockData(version, username, xuid, deviceOs, languageCode, inputMode,
|
||||
uiProfile, ip, linkedPlayer, fromProxy, subscribeId, verifyCode, EXPECTED_LENGTH);
|
||||
}
|
||||
|
||||
public static BedrockData of(
|
||||
String version, String username, String xuid, int deviceOs,
|
||||
String languageCode, int uiProfile, int inputMode, String ip,
|
||||
int subscribeId, String verifyCode) {
|
||||
return of(version, username, xuid, deviceOs, languageCode, uiProfile, inputMode, ip, null,
|
||||
false, subscribeId, verifyCode);
|
||||
}
|
||||
|
||||
public static BedrockData fromString(String data) {
|
||||
String[] split = data.split("\0");
|
||||
if (split.length != EXPECTED_LENGTH) {
|
||||
return emptyData(split.length);
|
||||
}
|
||||
|
||||
LinkedPlayer linkedPlayer = LinkedPlayer.fromString(split[8]);
|
||||
// The format is the same as the order of the fields in this class
|
||||
return new BedrockData(
|
||||
split[0], split[1], split[2], Integer.parseInt(split[3]), split[4],
|
||||
Integer.parseInt(split[5]), Integer.parseInt(split[6]), split[7], linkedPlayer,
|
||||
"1".equals(split[9]), Integer.parseInt(split[10]), split[11], split.length
|
||||
);
|
||||
}
|
||||
|
||||
private static BedrockData emptyData(int dataLength) {
|
||||
return new BedrockData(null, null, null, -1, null, -1, -1, null, null, false, -1, null,
|
||||
dataLength);
|
||||
}
|
||||
|
||||
public boolean hasPlayerLink() {
|
||||
return linkedPlayer != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
// The format is the same as the order of the fields in this class
|
||||
return version + '\0' + username + '\0' + xuid + '\0' + deviceOs + '\0' +
|
||||
languageCode + '\0' + uiProfile + '\0' + inputMode + '\0' + ip + '\0' +
|
||||
(linkedPlayer != null ? linkedPlayer.toString() : "null") + '\0' +
|
||||
(fromProxy ? 1 : 0) + '\0' + subscribeId + '\0' + verifyCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BedrockData clone() throws CloneNotSupportedException {
|
||||
return (BedrockData) super.clone();
|
||||
}
|
||||
}
|
||||
@@ -38,6 +38,7 @@ import org.bstats.charts.DrilldownPie;
|
||||
import org.bstats.charts.SimplePie;
|
||||
import org.bstats.charts.SingleLineChart;
|
||||
import org.bstats.json.JsonObjectBuilder;
|
||||
import org.geysermc.api.GeyserApiBase;
|
||||
import org.geysermc.floodgate.api.FloodgateApi;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.config.FloodgateConfig;
|
||||
@@ -49,7 +50,7 @@ public final class Metrics {
|
||||
private final MetricsBase metricsBase;
|
||||
|
||||
@Inject
|
||||
Metrics(FloodgateConfig config, PlatformUtils platformUtils, FloodgateApi api,
|
||||
Metrics(FloodgateConfig config, PlatformUtils platformUtils, GeyserApiBase api,
|
||||
@Named("implementationName") String implementationName, FloodgateLogger logger) {
|
||||
|
||||
MetricsConfig metricsConfig = config.getMetrics();
|
||||
@@ -71,12 +72,12 @@ public final class Metrics {
|
||||
);
|
||||
|
||||
metricsBase.addCustomChart(
|
||||
new SingleLineChart("players", api::getPlayerCount)
|
||||
new SingleLineChart("players", api::onlineConnectionsCount)
|
||||
);
|
||||
|
||||
metricsBase.addCustomChart(
|
||||
new DrilldownPie("player_count", () -> {
|
||||
int playerCount = api.getPlayerCount();
|
||||
int playerCount = api.onlineConnectionsCount();
|
||||
// 0 = 0 - 4, 9 = 5 - 9, etc.
|
||||
int category = playerCount / 5 * 5;
|
||||
String categoryName = category + " - " + (category + 4);
|
||||
|
||||
@@ -143,30 +143,6 @@ public interface FloodgatePlayer {
|
||||
return FloodgateApi.getInstance().transferPlayer(getCorrectUniqueId(), address, port);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
boolean hasProperty(PropertyKey key);
|
||||
|
||||
@Deprecated
|
||||
boolean hasProperty(String key);
|
||||
|
||||
@Deprecated
|
||||
<T> T getProperty(PropertyKey key);
|
||||
|
||||
@Deprecated
|
||||
<T> T getProperty(String key);
|
||||
|
||||
@Deprecated
|
||||
<T> T removeProperty(PropertyKey key);
|
||||
|
||||
@Deprecated
|
||||
<T> T removeProperty(String key);
|
||||
|
||||
@Deprecated
|
||||
<T> T addProperty(PropertyKey key, Object value);
|
||||
|
||||
@Deprecated
|
||||
<T> T addProperty(String key, Object value);
|
||||
|
||||
/**
|
||||
* Casts the FloodgatePlayer instance to a class that extends FloodgatePlayer.
|
||||
*
|
||||
@@ -3,7 +3,7 @@ enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
|
||||
dependencyResolutionManagement {
|
||||
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||
repositories {
|
||||
// mavenLocal()
|
||||
mavenLocal()
|
||||
|
||||
// Geyser, Cumulus etc.
|
||||
maven("https://repo.opencollab.dev/maven-releases") {
|
||||
@@ -62,7 +62,7 @@ pluginManagement {
|
||||
|
||||
rootProject.name = "floodgate-parent"
|
||||
|
||||
include(":api")
|
||||
include(":legacy-api")
|
||||
include(":ap")
|
||||
include(":core")
|
||||
include(":bungee")
|
||||
|
||||
@@ -39,6 +39,7 @@ public final class SpigotPlugin extends JavaPlugin {
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
// TODO don't enable if onLoad failed
|
||||
try {
|
||||
platform.enable();
|
||||
} catch (Exception exception) {
|
||||
|
||||
@@ -29,11 +29,12 @@ import com.google.inject.Inject;
|
||||
import com.google.inject.name.Named;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.util.AttributeKey;
|
||||
import org.geysermc.api.connection.Connection;
|
||||
import org.geysermc.floodgate.api.SimpleFloodgateApi;
|
||||
import org.geysermc.floodgate.api.inject.InjectorAddon;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
import org.geysermc.floodgate.config.FloodgateConfig;
|
||||
import org.geysermc.floodgate.player.Connection;
|
||||
import org.geysermc.floodgate.player.FloodgateHandshakeHandler;
|
||||
|
||||
public final class SpigotDataAddon implements InjectorAddon {
|
||||
@@ -52,7 +53,7 @@ public final class SpigotDataAddon implements InjectorAddon {
|
||||
|
||||
@Inject
|
||||
@Named("playerAttribute")
|
||||
private AttributeKey<FloodgatePlayer> playerAttribute;
|
||||
private AttributeKey<Connection> playerAttribute;
|
||||
|
||||
@Override
|
||||
public void onInject(Channel channel, boolean toServer) {
|
||||
@@ -65,9 +66,9 @@ public final class SpigotDataAddon implements InjectorAddon {
|
||||
|
||||
@Override
|
||||
public void onChannelClosed(Channel channel) {
|
||||
FloodgatePlayer player = channel.attr(playerAttribute).get();
|
||||
Connection player = channel.attr(playerAttribute).get();
|
||||
if (player != null && api.setPendingRemove(player)) {
|
||||
logger.translatedInfo("floodgate.ingame.disconnect_name", player.getCorrectUsername());
|
||||
logger.translatedInfo("floodgate.ingame.disconnect_name", player.javaUsername());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ import io.netty.util.AttributeKey;
|
||||
import java.net.InetSocketAddress;
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
import org.geysermc.floodgate.config.FloodgateConfig;
|
||||
import org.geysermc.floodgate.player.Connection;
|
||||
import org.geysermc.floodgate.player.FloodgateHandshakeHandler;
|
||||
import org.geysermc.floodgate.player.FloodgateHandshakeHandler.HandshakeResult;
|
||||
import org.geysermc.floodgate.util.ClassNames;
|
||||
@@ -41,7 +42,7 @@ import org.geysermc.floodgate.util.ProxyUtils;
|
||||
|
||||
public final class SpigotDataHandler extends CommonDataHandler {
|
||||
private Object networkManager;
|
||||
private FloodgatePlayer player;
|
||||
private Connection player;
|
||||
private boolean proxyData;
|
||||
|
||||
public SpigotDataHandler(
|
||||
@@ -80,7 +81,7 @@ public final class SpigotDataHandler extends CommonDataHandler {
|
||||
|
||||
if (!proxyData) {
|
||||
// Use a spoofedUUID for initUUID (just like Bungeecord)
|
||||
setValue(networkManager, "spoofedUUID", player.getCorrectUniqueId());
|
||||
setValue(networkManager, "spoofedUUID", player.javaUuid());
|
||||
}
|
||||
|
||||
// we can only remove the handler if the data is proxy data and username validation doesn't
|
||||
@@ -150,7 +151,7 @@ public final class SpigotDataHandler extends CommonDataHandler {
|
||||
|
||||
// set the player his GameProfile, we can't change the username without this
|
||||
GameProfile gameProfile = new GameProfile(
|
||||
player.getCorrectUniqueId(), player.getCorrectUsername()
|
||||
player.javaUuid(), player.javaUsername()
|
||||
);
|
||||
setValue(packetListener, ClassNames.LOGIN_PROFILE, gameProfile);
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.geysermc.api.connection.Connection;
|
||||
import org.geysermc.floodgate.api.SimpleFloodgateApi;
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
|
||||
@@ -46,7 +47,7 @@ public final class PaperProfileListener implements Listener {
|
||||
return;
|
||||
}
|
||||
|
||||
FloodgatePlayer player = api.getPlayer(id);
|
||||
Connection player = api.connectionByUuid(id);
|
||||
if (player == null || player.isLinked()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -32,9 +32,9 @@ import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerLoginEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.geysermc.api.connection.Connection;
|
||||
import org.geysermc.floodgate.api.SimpleFloodgateApi;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
import org.geysermc.floodgate.util.LanguageManager;
|
||||
|
||||
public final class SpigotListener implements Listener {
|
||||
@@ -51,15 +51,15 @@ public final class SpigotListener implements Listener {
|
||||
|
||||
// if there was another player with the same uuid online,
|
||||
// he would've been disconnected by now
|
||||
FloodgatePlayer player = api.getPlayer(uniqueId);
|
||||
Connection player = api.connectionByUuid(uniqueId);
|
||||
if (player != null) {
|
||||
//todo we should probably move this log message earlier in the process, so that we know
|
||||
// that Floodgate has done its job
|
||||
logger.translatedInfo(
|
||||
"floodgate.ingame.login_name",
|
||||
player.getCorrectUsername(), player.getCorrectUniqueId()
|
||||
player.javaUsername(), player.javaUuid()
|
||||
);
|
||||
languageManager.loadLocale(player.getLanguageCode());
|
||||
languageManager.loadLocale(player.languageCode());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ import java.util.logging.Logger;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.geysermc.api.GeyserApiBase;
|
||||
import org.geysermc.floodgate.api.FloodgateApi;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.inject.CommonPlatformInjector;
|
||||
@@ -78,7 +79,7 @@ public final class SpigotPlatformModule extends AbstractModule {
|
||||
@Provides
|
||||
@Singleton
|
||||
public CommandUtil commandUtil(
|
||||
FloodgateApi api,
|
||||
GeyserApiBase api,
|
||||
SpigotVersionSpecificMethods versionSpecificMethods,
|
||||
LanguageManager languageManager) {
|
||||
return new SpigotCommandUtil(
|
||||
|
||||
@@ -32,6 +32,7 @@ import com.mojang.authlib.properties.PropertyMap;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.geysermc.api.connection.Connection;
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
import org.geysermc.floodgate.skin.SkinApplier;
|
||||
import org.geysermc.floodgate.skin.SkinData;
|
||||
@@ -51,13 +52,13 @@ public final class SpigotSkinApplier implements SkinApplier {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applySkin(FloodgatePlayer floodgatePlayer, SkinData skinData) {
|
||||
applySkin0(floodgatePlayer, skinData, true);
|
||||
public void applySkin(Connection connection, SkinData skinData) {
|
||||
applySkin0(connection, skinData, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSkin(FloodgatePlayer floodgatePlayer) {
|
||||
Player player = Bukkit.getPlayer(floodgatePlayer.getCorrectUniqueId());
|
||||
public boolean hasSkin(Connection connection) {
|
||||
Player player = Bukkit.getPlayer(connection.javaUuid());
|
||||
|
||||
if (player == null) {
|
||||
return false;
|
||||
@@ -73,8 +74,8 @@ public final class SpigotSkinApplier implements SkinApplier {
|
||||
return false;
|
||||
}
|
||||
|
||||
private void applySkin0(FloodgatePlayer floodgatePlayer, SkinData skinData, boolean firstTry) {
|
||||
Player player = Bukkit.getPlayer(floodgatePlayer.getCorrectUniqueId());
|
||||
private void applySkin0(Connection floodgatePlayer, SkinData skinData, boolean firstTry) {
|
||||
Player player = Bukkit.getPlayer(floodgatePlayer.javaUuid());
|
||||
|
||||
// player is probably not logged in yet
|
||||
if (player == null) {
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.geysermc.api.GeyserApiBase;
|
||||
import org.geysermc.floodgate.api.FloodgateApi;
|
||||
import org.geysermc.floodgate.platform.command.CommandUtil;
|
||||
import org.geysermc.floodgate.player.UserAudience;
|
||||
@@ -48,7 +49,7 @@ public final class SpigotCommandUtil extends CommandUtil {
|
||||
public SpigotCommandUtil(
|
||||
LanguageManager manager,
|
||||
Server server,
|
||||
FloodgateApi api,
|
||||
GeyserApiBase api,
|
||||
SpigotVersionSpecificMethods versionSpecificMethods,
|
||||
JavaPlugin plugin) {
|
||||
super(manager, api);
|
||||
|
||||
@@ -35,6 +35,7 @@ import java.util.UUID;
|
||||
import org.geysermc.floodgate.api.packet.PacketHandler;
|
||||
import org.geysermc.floodgate.api.packet.PacketHandlers;
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
import org.geysermc.floodgate.player.Connection;
|
||||
|
||||
public class SpigotProtocolSupportHandler implements PacketHandler {
|
||||
private static final Method getFromChannel;
|
||||
@@ -81,7 +82,7 @@ public class SpigotProtocolSupportHandler implements PacketHandler {
|
||||
|
||||
@Inject
|
||||
@Named("playerAttribute")
|
||||
private AttributeKey<FloodgatePlayer> playerAttribute;
|
||||
private AttributeKey<Connection> playerAttribute;
|
||||
|
||||
@Inject
|
||||
public void register(PacketHandlers packetHandlers) {
|
||||
@@ -90,7 +91,7 @@ public class SpigotProtocolSupportHandler implements PacketHandler {
|
||||
|
||||
@Override
|
||||
public Object handle(ChannelHandlerContext ctx, Object packet, boolean serverbound) {
|
||||
FloodgatePlayer player = ctx.channel().attr(playerAttribute).get();
|
||||
Connection player = ctx.channel().attr(playerAttribute).get();
|
||||
if (player == null) {
|
||||
return packet;
|
||||
}
|
||||
@@ -99,14 +100,14 @@ public class SpigotProtocolSupportHandler implements PacketHandler {
|
||||
Object profile = ReflectionUtils.invoke(connection, getLoginProfile);
|
||||
|
||||
// set correct uuid and name on ProtocolSupport's end, since we skip the LoginStart
|
||||
ReflectionUtils.invoke(profile, setName, player.getCorrectUsername());
|
||||
ReflectionUtils.invoke(profile, setOriginalName, player.getCorrectUsername());
|
||||
ReflectionUtils.invoke(profile, setUuid, player.getCorrectUniqueId());
|
||||
ReflectionUtils.invoke(profile, setOriginalUuid, player.getCorrectUniqueId());
|
||||
ReflectionUtils.invoke(profile, setName, player.javaUsername());
|
||||
ReflectionUtils.invoke(profile, setOriginalName, player.javaUsername());
|
||||
ReflectionUtils.invoke(profile, setUuid, player.javaUuid());
|
||||
ReflectionUtils.invoke(profile, setOriginalUuid, player.javaUuid());
|
||||
|
||||
Object temp = ReflectionUtils.invoke(connection, getNetworkManagerWrapper);
|
||||
temp = ReflectionUtils.invoke(temp, getPacketListener);
|
||||
ReflectionUtils.invoke(temp, handleLoginStart, player.getCorrectUsername());
|
||||
ReflectionUtils.invoke(temp, handleLoginStart, player.javaUsername());
|
||||
return packet;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ import org.bukkit.event.Event;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.geysermc.api.Geyser;
|
||||
import org.geysermc.floodgate.api.FloodgateApi;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -69,7 +70,7 @@ public final class SpigotProtocolSupportListener {
|
||||
return;
|
||||
}
|
||||
|
||||
if (FloodgateApi.getInstance().isFloodgatePlayer(uuid)) {
|
||||
if (Geyser.api().isBedrockPlayer(uuid)) {
|
||||
// otherwise ProtocolSupport attempts to connect with online mode
|
||||
ReflectionUtils.invoke(event, setOnlineMode, false);
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ import org.geysermc.floodgate.api.inject.InjectorAddon;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
import org.geysermc.floodgate.config.ProxyFloodgateConfig;
|
||||
import org.geysermc.floodgate.player.Connection;
|
||||
import org.geysermc.floodgate.player.FloodgateHandshakeHandler;
|
||||
|
||||
public final class VelocityDataAddon implements InjectorAddon {
|
||||
@@ -62,7 +63,7 @@ public final class VelocityDataAddon implements InjectorAddon {
|
||||
|
||||
@Inject
|
||||
@Named("playerAttribute")
|
||||
private AttributeKey<FloodgatePlayer> playerAttribute;
|
||||
private AttributeKey<Connection> playerAttribute;
|
||||
|
||||
@Override
|
||||
public void onInject(Channel channel, boolean toServer) {
|
||||
@@ -88,9 +89,9 @@ public final class VelocityDataAddon implements InjectorAddon {
|
||||
|
||||
@Override
|
||||
public void onChannelClosed(Channel channel) {
|
||||
FloodgatePlayer player = channel.attr(playerAttribute).get();
|
||||
Connection player = channel.attr(playerAttribute).get();
|
||||
if (player != null && api.setPendingRemove(player)) {
|
||||
logger.translatedInfo("floodgate.ingame.disconnect_name", player.getUsername());
|
||||
logger.translatedInfo("floodgate.ingame.disconnect_name", player.javaUsername());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ import java.net.InetSocketAddress;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
import org.geysermc.floodgate.config.FloodgateConfig;
|
||||
import org.geysermc.floodgate.player.Connection;
|
||||
import org.geysermc.floodgate.player.FloodgateHandshakeHandler;
|
||||
import org.geysermc.floodgate.player.FloodgateHandshakeHandler.HandshakeResult;
|
||||
import org.geysermc.floodgate.player.FloodgateHandshakeHandler.ResultType;
|
||||
@@ -113,9 +114,9 @@ public final class VelocityProxyDataHandler extends CommonDataHandler {
|
||||
@Override
|
||||
protected boolean shouldRemoveHandler(HandshakeResult result) {
|
||||
if (result.getResultType() == ResultType.SUCCESS) {
|
||||
FloodgatePlayer player = result.getFloodgatePlayer();
|
||||
Connection player = result.getFloodgatePlayer();
|
||||
logger.info("Floodgate player who is logged in as {} {} joined",
|
||||
player.getCorrectUsername(), player.getCorrectUniqueId());
|
||||
player.javaUsername(), player.javaUuid());
|
||||
|
||||
// the way Velocity stores whether to force key authentication
|
||||
boolean forceKeyAuthentication = Boolean.getBoolean("auth.forceSecureProfiles");
|
||||
|
||||
@@ -41,8 +41,8 @@ import io.netty.channel.ChannelOutboundHandlerAdapter;
|
||||
import io.netty.channel.ChannelPromise;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import org.geysermc.api.connection.Connection;
|
||||
import org.geysermc.floodgate.api.ProxyFloodgateApi;
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
import org.geysermc.floodgate.player.FloodgatePlayerImpl;
|
||||
import org.geysermc.floodgate.util.BedrockData;
|
||||
|
||||
@@ -101,7 +101,7 @@ public final class VelocityServerDataHandler extends ChannelOutboundHandlerAdapt
|
||||
Player velocityPlayer = castedInvoke(association, GET_PLAYER);
|
||||
|
||||
//noinspection ConstantConditions
|
||||
FloodgatePlayer player = api.getPlayer(velocityPlayer.getUniqueId());
|
||||
Connection player = api.connectionByUuid(velocityPlayer.getUniqueId());
|
||||
|
||||
//todo use something similar to what's written below for a more direct approach
|
||||
|
||||
@@ -112,7 +112,7 @@ public final class VelocityServerDataHandler extends ChannelOutboundHandlerAdapt
|
||||
//FloodgatePlayer player = playerChannel.attr(playerAttribute).get();
|
||||
if (player != null) {
|
||||
// Player is a Floodgate player
|
||||
BedrockData data = player.as(FloodgatePlayerImpl.class).toBedrockData();
|
||||
BedrockData data = ((FloodgatePlayerImpl) player).toBedrockData();
|
||||
String encryptedData = api.createEncryptedDataString(data);
|
||||
|
||||
// use the same system that we use on bungee, our data goes before all the other data
|
||||
|
||||
@@ -52,9 +52,9 @@ import java.util.Collections;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.geysermc.api.connection.Connection;
|
||||
import org.geysermc.floodgate.api.ProxyFloodgateApi;
|
||||
import org.geysermc.floodgate.api.logger.FloodgateLogger;
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
import org.geysermc.floodgate.config.ProxyFloodgateConfig;
|
||||
import org.geysermc.floodgate.util.LanguageManager;
|
||||
|
||||
@@ -84,7 +84,7 @@ public final class VelocityListener {
|
||||
CHANNEL = getFieldOfType(minecraftConnection, Channel.class);
|
||||
}
|
||||
|
||||
private final Cache<InboundConnection, FloodgatePlayer> playerCache =
|
||||
private final Cache<InboundConnection, Connection> playerCache =
|
||||
CacheBuilder.newBuilder()
|
||||
.maximumSize(500)
|
||||
.expireAfterAccess(20, TimeUnit.SECONDS)
|
||||
@@ -97,7 +97,7 @@ public final class VelocityListener {
|
||||
|
||||
@Inject
|
||||
@Named("playerAttribute")
|
||||
private AttributeKey<FloodgatePlayer> playerAttribute;
|
||||
private AttributeKey<Connection> playerAttribute;
|
||||
|
||||
@Inject
|
||||
@Named("kickMessageAttribute")
|
||||
@@ -105,7 +105,7 @@ public final class VelocityListener {
|
||||
|
||||
@Subscribe(order = PostOrder.EARLY)
|
||||
public void onPreLogin(PreLoginEvent event) {
|
||||
FloodgatePlayer player = null;
|
||||
Connection player = null;
|
||||
String kickMessage;
|
||||
try {
|
||||
InboundConnection connection = event.getConnection();
|
||||
@@ -140,13 +140,13 @@ public final class VelocityListener {
|
||||
|
||||
@Subscribe(order = PostOrder.EARLY)
|
||||
public void onGameProfileRequest(GameProfileRequestEvent event) {
|
||||
FloodgatePlayer player = playerCache.getIfPresent(event.getConnection());
|
||||
Connection player = playerCache.getIfPresent(event.getConnection());
|
||||
if (player != null) {
|
||||
playerCache.invalidate(event.getConnection());
|
||||
|
||||
GameProfile profile = new GameProfile(
|
||||
player.getCorrectUniqueId(),
|
||||
player.getCorrectUsername(),
|
||||
player.javaUuid(),
|
||||
player.javaUsername(),
|
||||
Collections.emptyList()
|
||||
);
|
||||
// The texture properties addition is to fix the February 2 2022 Mojang authentication changes
|
||||
@@ -160,9 +160,9 @@ public final class VelocityListener {
|
||||
@Subscribe(order = PostOrder.LAST)
|
||||
public void onLogin(LoginEvent event) {
|
||||
if (event.getResult().isAllowed()) {
|
||||
FloodgatePlayer player = api.getPlayer(event.getPlayer().getUniqueId());
|
||||
Connection player = api.connectionByUuid(event.getPlayer().getUniqueId());
|
||||
if (player != null) {
|
||||
languageManager.loadLocale(player.getLanguageCode());
|
||||
languageManager.loadLocale(player.languageCode());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.geysermc.api.GeyserApiBase;
|
||||
import org.geysermc.floodgate.api.FloodgateApi;
|
||||
import org.geysermc.floodgate.platform.command.CommandUtil;
|
||||
import org.geysermc.floodgate.player.UserAudience;
|
||||
@@ -46,7 +47,7 @@ public final class VelocityCommandUtil extends CommandUtil {
|
||||
@Inject private ProxyServer server;
|
||||
|
||||
@Inject
|
||||
public VelocityCommandUtil(LanguageManager manager, FloodgateApi api) {
|
||||
public VelocityCommandUtil(LanguageManager manager, GeyserApiBase api) {
|
||||
super(manager, api);
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.geysermc.floodgate.api.player.FloodgatePlayer;
|
||||
import org.geysermc.api.connection.Connection;
|
||||
import org.geysermc.floodgate.skin.SkinApplier;
|
||||
import org.geysermc.floodgate.skin.SkinData;
|
||||
|
||||
@@ -41,8 +41,8 @@ public class VelocitySkinApplier implements SkinApplier {
|
||||
private final ProxyServer server;
|
||||
|
||||
@Override
|
||||
public void applySkin(FloodgatePlayer floodgatePlayer, SkinData skinData) {
|
||||
server.getPlayer(floodgatePlayer.getCorrectUniqueId()).ifPresent(player -> {
|
||||
public void applySkin(Connection connection, SkinData skinData) {
|
||||
server.getPlayer(connection.javaUuid()).ifPresent(player -> {
|
||||
List<Property> properties = new ArrayList<>(player.getGameProfileProperties());
|
||||
properties.add(new Property("textures", skinData.getValue(), skinData.getSignature()));
|
||||
player.setGameProfileProperties(properties);
|
||||
@@ -50,8 +50,8 @@ public class VelocitySkinApplier implements SkinApplier {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSkin(FloodgatePlayer floodgatePlayer) {
|
||||
Optional<Player> player = server.getPlayer(floodgatePlayer.getCorrectUniqueId());
|
||||
public boolean hasSkin(Connection connection) {
|
||||
Optional<Player> player = server.getPlayer(connection.javaUuid());
|
||||
|
||||
if (player.isPresent()) {
|
||||
for (Property property : player.get().getGameProfileProperties()) {
|
||||
|
||||
Reference in New Issue
Block a user