diff --git a/bootstrap/bungeecord/build.gradle.kts b/bootstrap/bungeecord/build.gradle.kts index 3e0e9c147..e95ddd618 100644 --- a/bootstrap/bungeecord/build.gradle.kts +++ b/bootstrap/bungeecord/build.gradle.kts @@ -2,6 +2,8 @@ dependencies { api(projects.core) implementation(libs.adventure.text.serializer.bungeecord) + + implementation("org.geysermc.floodgate", "bungee", "2.2.0-SNAPSHOT") } platformRelocate("net.md_5.bungee.jni") diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/BungeeHybridListener.java b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/BungeeHybridListener.java new file mode 100644 index 000000000..8d699ffd3 --- /dev/null +++ b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/BungeeHybridListener.java @@ -0,0 +1,101 @@ +/* + * 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.geyser.platform.bungeecord; + +import net.md_5.bungee.api.plugin.Listener; + +public final class BungeeHybridListener implements Listener { +// // TODO consolidate with Floodgate +// private static final Field CHANNEL_WRAPPER; +// private static final Field PLAYER_NAME; +// +// static { +// CHANNEL_WRAPPER = +// ReflectionUtils.getFieldOfType(InitialHandler.class, ChannelWrapper.class); +// checkNotNull(CHANNEL_WRAPPER, "ChannelWrapper field cannot be null"); +// +// PLAYER_NAME = ReflectionUtils.getField(InitialHandler.class, "name"); +// checkNotNull(PLAYER_NAME, "Initial name field cannot be null"); +// } +// +// @EventHandler(priority = EventPriority.LOWEST) +// public void onPreLogin(PreLoginEvent event) { +// // well, no reason to check if the player will be kicked anyway +// if (event.isCancelled()) { +// return; +// } +// +// PendingConnection connection = event.getConnection(); +// Connection player = getPlayer(connection); +// if (player != null) { +// connection.setOnlineMode(false); +// connection.setUniqueId(player.javaUuid()); +// ReflectionUtils.setValue(connection, PLAYER_NAME, player.javaUsername()); +// } +// } +// +// @EventHandler(priority = EventPriority.LOW) +// public void onServerConnect(ServerConnectEvent event) { +// boolean sendFloodgateData = false; // TODO +// if (!sendFloodgateData) { +// return; // TODO just don't register event? +// } +// +// PendingConnection connection = event.getPlayer().getPendingConnection(); +// Connection player = getPlayer(connection); +// if (player != null) { +// Handshake handshake = ReflectionUtils.getCastedValue(connection, "handshake"); +// BedrockData data = ((FloodgateConnection) player).toBedrockData(); // FIXME +// String encryptedData = ((ProxyHybridProvider) GeyserImpl.getInstance().getHybridProvider()) +// .createEncryptedDataString(data); +// +// String address = handshake.getHost(); +// +// // our data goes before all the other data +// int addressFinished = address.indexOf('\0'); +// String originalAddress; +// String remaining; +// if (addressFinished != -1) { +// originalAddress = address.substring(0, addressFinished); +// remaining = address.substring(addressFinished); +// } else { +// originalAddress = address; +// remaining = ""; +// } +// +// handshake.setHost(originalAddress + '\0' + encryptedData + remaining); +// // Bungeecord will add its data after our data +// } +// } +// +// @Nullable +// private Connection getPlayer(PendingConnection connection) { +// ChannelWrapper wrapper = ReflectionUtils.getCastedValue(connection, CHANNEL_WRAPPER); +// Channel channel = wrapper.getHandle(); +// +// return channel.attr(IntegratedHybridProvider.SESSION_KEY).get(); // TODO re-use Floodgate's attribute key here? +// } +} diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeeConfiguration.java b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeeConfiguration.java index bc084a34e..3b43f2cb7 100644 --- a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeeConfiguration.java +++ b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeeConfiguration.java @@ -40,6 +40,7 @@ public final class GeyserBungeeConfiguration extends GeyserJacksonConfiguration @JsonIgnore private Path floodgateKeyPath; + // TODO remove public void loadFloodgate(GeyserBungeePlugin plugin) { Plugin floodgate = plugin.getProxy().getPluginManager().getPlugin("floodgate"); Path geyserDataFolder = plugin.getDataFolder().toPath(); diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java index 4141a8dbc..a4531afcb 100644 --- a/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java +++ b/bootstrap/bungeecord/src/main/java/org/geysermc/geyser/platform/bungeecord/GeyserBungeePlugin.java @@ -31,19 +31,25 @@ import net.md_5.bungee.api.config.ListenerInfo; import net.md_5.bungee.api.plugin.Plugin; import net.md_5.bungee.protocol.ProtocolConstants; import org.checkerframework.checker.nullness.qual.Nullable; -import org.geysermc.common.PlatformType; +import org.geysermc.floodgate.BungeePlatform; +import org.geysermc.floodgate.pluginmessage.BungeeSkinApplier; +import org.geysermc.floodgate.skin.SkinApplier; import org.geysermc.geyser.GeyserBootstrap; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.command.Command; import org.geysermc.geyser.api.extension.Extension; +import org.geysermc.geyser.api.network.AuthType; import org.geysermc.geyser.command.GeyserCommandManager; import org.geysermc.geyser.configuration.GeyserConfiguration; import org.geysermc.geyser.dump.BootstrapDumpInfo; +import org.geysermc.geyser.hybrid.HybridProvider; +import org.geysermc.geyser.hybrid.ProxyHybridProvider; import org.geysermc.geyser.ping.GeyserLegacyPingPassthrough; import org.geysermc.geyser.ping.IGeyserPingPassthrough; import org.geysermc.geyser.platform.bungeecord.command.GeyserBungeeCommandExecutor; import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.util.FileUtils; +import org.geysermc.geyser.util.PlatformType; import org.jetbrains.annotations.NotNull; import java.io.File; @@ -106,15 +112,29 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap { this.geyserLogger = new GeyserBungeeLogger(getLogger(), geyserConfig.isDebugMode()); GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger); - this.geyser = GeyserImpl.load(PlatformType.BUNGEECORD, this); + this.geyser = GeyserImpl.load(PlatformType.BUNGEECORD, this, null); } @Override public void onEnable() { - // Remove this in like a year - if (getProxy().getPluginManager().getPlugin("floodgate-bungee") != null) { - geyserLogger.severe(GeyserLocale.getLocaleStringLog("geyser.bootstrap.floodgate.outdated", "https://ci.opencollab.dev/job/GeyserMC/job/Floodgate/job/master/")); - return; + if (getProxy().getConfig().getListeners().size() == 1) { + ListenerInfo listener = getProxy().getConfig().getListeners().toArray(new ListenerInfo[0])[0]; + + InetSocketAddress javaAddr = listener.getHost(); + + // By default this should be localhost but may need to be changed in some circumstances + if (this.geyserConfig.getRemote().address().equalsIgnoreCase("auto")) { + this.geyserConfig.setAutoconfiguredRemote(true); + // Don't use localhost if not listening on all interfaces + if (!javaAddr.getHostString().equals("0.0.0.0") && !javaAddr.getHostString().equals("")) { + this.geyserConfig.getRemote().setAddress(javaAddr.getHostString()); + } + this.geyserConfig.getRemote().setPort(javaAddr.getPort()); + } + + if (geyserConfig.getBedrock().isCloneRemotePort()) { + geyserConfig.getBedrock().setPort(javaAddr.getPort()); + } } // Force-disable query if enabled, or else Geyser won't enable @@ -135,6 +155,14 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap { } } + if (getProxy().getPluginManager().getPlugin("floodgate") != null) { + geyserLogger.warning("WHY DO YOU HAVE FLOODGATE INSTALLED???1/"); + } + + if (geyserConfig.getRemote().authType() == AuthType.FLOODGATE) { + getProxy().getPluginManager().registerListener(this, new BungeeHybridListener()); + } + // Big hack - Bungee does not provide us an event to listen to, so schedule a repeating // task that waits for a field to be filled which is set after the plugin enable // process is complete @@ -271,4 +299,15 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap { .map(info -> (InetSocketAddress) info.getSocketAddress()) .findFirst(); } + + @Override + public HybridProvider createHybridProvider(GeyserImpl geyser) { + return new ProxyHybridProvider(geyser); + } + + @Override + public SkinApplier createSkinApplier() { + new BungeePlatform(this); // TODO hack to ensure ReflectionUtils prefix is applied and I don't forget about dealing with it + return new BungeeSkinApplier(null); // Also TODO + } } diff --git a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricMod.java b/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricMod.java index fdc820b19..64a0c356f 100644 --- a/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricMod.java +++ b/bootstrap/fabric/src/main/java/org/geysermc/geyser/platform/fabric/GeyserFabricMod.java @@ -36,7 +36,6 @@ import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; import net.minecraft.server.MinecraftServer; import org.apache.logging.log4j.LogManager; -import org.geysermc.common.PlatformType; import org.geysermc.geyser.GeyserBootstrap; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserLogger; @@ -52,6 +51,7 @@ import org.geysermc.geyser.platform.fabric.command.GeyserFabricCommandExecutor; import org.geysermc.geyser.platform.fabric.world.GeyserFabricWorldManager; import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.util.FileUtils; +import org.geysermc.geyser.util.PlatformType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/bootstrap/spigot/build.gradle.kts b/bootstrap/spigot/build.gradle.kts index 58ea763eb..29df5d449 100644 --- a/bootstrap/spigot/build.gradle.kts +++ b/bootstrap/spigot/build.gradle.kts @@ -21,6 +21,8 @@ dependencies { attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 17) } } + + implementation("org.geysermc.floodgate", "spigot", "2.2.0-SNAPSHOT") } platformRelocate("it.unimi.dsi.fastutil") @@ -32,6 +34,7 @@ platformRelocate("me.lucko.commodore") // These dependencies are already present on the platform provided(libs.viaversion) +provided("com.mojang", "authlib", "1.5.21") application { mainClass.set("org.geysermc.geyser.platform.spigot.GeyserSpigotMain") diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotConfiguration.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotConfiguration.java index 3320ffa65..a4db21371 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotConfiguration.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotConfiguration.java @@ -41,6 +41,7 @@ public final class GeyserSpigotConfiguration extends GeyserJacksonConfiguration @JsonIgnore private Path floodgateKeyPath; + // TODO REMOVE public void loadFloodgate(GeyserSpigotPlugin plugin) { Plugin floodgate = Bukkit.getPluginManager().getPlugin("floodgate"); Path geyserDataFolder = plugin.getDataFolder().toPath(); diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotInjector.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotInjector.java index e3d73fb19..5f78c5d16 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotInjector.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotInjector.java @@ -33,6 +33,8 @@ import io.netty.channel.local.LocalAddress; import io.netty.util.concurrent.DefaultThreadFactory; import org.bukkit.Bukkit; import org.geysermc.geyser.GeyserBootstrap; +import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.api.network.AuthType; import org.geysermc.geyser.network.netty.GeyserInjector; import org.geysermc.geyser.network.netty.LocalServerChannelWrapper; import org.geysermc.geyser.network.netty.LocalSession; @@ -119,10 +121,17 @@ public class GeyserSpigotInjector extends GeyserInjector { @Override protected void initChannel(Channel ch) throws Exception { initChannel.invoke(childHandler, ch); - if (bootstrap.getGeyserConfig().isDisableCompression() && GeyserSpigotCompressionDisabler.ENABLED) { ch.pipeline().addAfter("encoder", "geyser-compression-disabler", new GeyserSpigotCompressionDisabler()); } + + if (GeyserImpl.getInstance().getConfig().getRemote().authType() == AuthType.FLOODGATE) { + // we have to add the packet blocker in the data handler, otherwise ProtocolSupport breaks + ch.pipeline().addBefore( + "packet_handler", "geyser_data_handler", + new SpigotHybridChannelHandler() + ); + } } }) // Set to MAX_PRIORITY as MultithreadEventLoopGroup#newDefaultThreadFactory which DefaultEventLoopGroup implements does by default @@ -174,7 +183,7 @@ public class GeyserSpigotInjector extends GeyserInjector { */ private void workAroundWeirdBug(GeyserBootstrap bootstrap) { MinecraftProtocol protocol = new MinecraftProtocol(); - LocalSession session = new LocalSession(bootstrap.getGeyserConfig().getRemote().address(), + LocalSession session = new LocalSession(null, bootstrap.getGeyserConfig().getRemote().address(), bootstrap.getGeyserConfig().getRemote().port(), this.serverSocketAddress, InetAddress.getLoopbackAddress().getHostAddress(), protocol, protocol.createHelper()); session.connect(); diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java index a660d735b..45ea574fc 100644 --- a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/GeyserSpigotPlugin.java @@ -42,7 +42,9 @@ import org.bukkit.permissions.Permission; import org.bukkit.permissions.PermissionDefault; import org.bukkit.plugin.Plugin; import org.bukkit.plugin.java.JavaPlugin; -import org.geysermc.common.PlatformType; +import org.geysermc.floodgate.pluginmessage.SpigotSkinApplier; +import org.geysermc.floodgate.skin.SkinApplier; +import org.geysermc.floodgate.util.SpigotVersionSpecificMethods; import org.geysermc.geyser.Constants; import org.geysermc.geyser.GeyserBootstrap; import org.geysermc.geyser.GeyserImpl; @@ -52,6 +54,8 @@ import org.geysermc.geyser.api.extension.Extension; import org.geysermc.geyser.command.GeyserCommandManager; import org.geysermc.geyser.configuration.GeyserConfiguration; import org.geysermc.geyser.dump.BootstrapDumpInfo; +import org.geysermc.geyser.hybrid.HybridProvider; +import org.geysermc.geyser.hybrid.IntegratedHybridProvider; import org.geysermc.geyser.level.WorldManager; import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.ping.GeyserLegacyPingPassthrough; @@ -66,6 +70,7 @@ import org.geysermc.geyser.platform.spigot.world.manager.GeyserSpigotNativeWorld import org.geysermc.geyser.platform.spigot.world.manager.GeyserSpigotWorldManager; import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.util.FileUtils; +import org.geysermc.geyser.util.PlatformType; import org.jetbrains.annotations.NotNull; import java.io.File; @@ -154,7 +159,7 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger); - this.geyser = GeyserImpl.load(PlatformType.SPIGOT, this); + this.geyser = GeyserImpl.load(PlatformType.SPIGOT, this, null); } @Override @@ -165,11 +170,22 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { return; } - // Remove this in like a year - if (Bukkit.getPluginManager().getPlugin("floodgate-bukkit") != null) { - geyserLogger.severe(GeyserLocale.getLocaleStringLog("geyser.bootstrap.floodgate.outdated", Constants.FLOODGATE_DOWNLOAD_LOCATION)); - this.getPluginLoader().disablePlugin(this); - return; + // By default this should be localhost but may need to be changed in some circumstances + if (this.geyserConfig.getRemote().address().equalsIgnoreCase("auto")) { + geyserConfig.setAutoconfiguredRemote(true); + // Don't use localhost if not listening on all interfaces + if (!Bukkit.getIp().equals("0.0.0.0") && !Bukkit.getIp().equals("")) { + geyserConfig.getRemote().setAddress(Bukkit.getIp()); + } + geyserConfig.getRemote().setPort(Bukkit.getPort()); + } + + if (geyserConfig.getBedrock().isCloneRemotePort()) { + geyserConfig.getBedrock().setPort(Bukkit.getPort()); + } + + if (Bukkit.getPluginManager().getPlugin("floodgate") != null) { + geyserLogger.severe("WHY DO YOU HAVE FLOODGATE INSTALLED!!!!!!! REMOVE IT!!!!"); } this.geyserCommandManager = new GeyserSpigotCommandManager(geyser); @@ -408,6 +424,16 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap { return this.geyserInjector.getServerSocketAddress(); } + @Override + public HybridProvider createHybridProvider(GeyserImpl geyser) { + return new IntegratedHybridProvider(geyser); + } + + @Override + public SkinApplier createSkinApplier() { + return new SpigotSkinApplier(new SpigotVersionSpecificMethods(this), this); + } + /** * @return the server version before ViaVersion finishes initializing */ diff --git a/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/SpigotHybridChannelHandler.java b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/SpigotHybridChannelHandler.java new file mode 100644 index 000000000..acfd30f40 --- /dev/null +++ b/bootstrap/spigot/src/main/java/org/geysermc/geyser/platform/spigot/SpigotHybridChannelHandler.java @@ -0,0 +1,88 @@ +/* + * 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.geyser.platform.spigot; + +import com.mojang.authlib.GameProfile; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import org.geysermc.floodgate.util.ClassNames; +import org.geysermc.geyser.hybrid.IntegratedHybridProvider; +import org.geysermc.geyser.session.GeyserSession; + +import javax.annotation.Nonnull; + +import static org.geysermc.floodgate.util.ReflectionUtils.setValue; + +@ChannelHandler.Sharable +public final class SpigotHybridChannelHandler extends ChannelInboundHandlerAdapter { + + @Override + public void channelRead(@Nonnull ChannelHandlerContext ctx, @Nonnull Object packet) throws Exception { + GeyserSession session = ctx.channel().attr(IntegratedHybridProvider.SESSION_KEY).get(); + // TODO generify this code within Floodgate + if (ClassNames.LOGIN_START_PACKET.isInstance(packet)) { + Object networkManager = ctx.channel().pipeline().get("packet_handler"); + Object packetListener = ClassNames.PACKET_LISTENER.get(networkManager); + + setValue(networkManager, "spoofedUUID", session.javaUuid()); + + // check if the server is actually in the Login state + if (!ClassNames.LOGIN_LISTENER.isInstance(packetListener)) { + // player is not in the login state, abort + + // I would've liked to close the channel for security reasons, but our big friend + // ProtocolSupport, who likes to break things, doesn't work otherwise + ctx.pipeline().remove(this); + return; + } + + // set the player his GameProfile, we can't change the username without this + GameProfile gameProfile = new GameProfile( + // TODO testing only + session.javaUuid(), session.javaUsername() + ); + setValue(packetListener, ClassNames.LOGIN_PROFILE, gameProfile); + + // we have to fake the offline player (login) cycle + // just like on Spigot: + + // LoginListener#initUUID + // new LoginHandler().fireEvents(); + + // and the tick of LoginListener will do the rest + + ClassNames.INIT_UUID.invoke(packetListener); + + Object loginHandler = ClassNames.LOGIN_HANDLER_CONSTRUCTOR.newInstance(packetListener); + ClassNames.FIRE_LOGIN_EVENTS.invoke(loginHandler); + + ctx.pipeline().remove(this); + return; + } + ctx.fireChannelRead(packet); + } +} diff --git a/bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/GeyserSpongePlugin.java b/bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/GeyserSpongePlugin.java index dd84bf31c..dd86ed9c7 100644 --- a/bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/GeyserSpongePlugin.java +++ b/bootstrap/sponge/src/main/java/org/geysermc/geyser/platform/sponge/GeyserSpongePlugin.java @@ -27,7 +27,6 @@ package org.geysermc.geyser.platform.sponge; import com.google.inject.Inject; import org.apache.logging.log4j.Logger; -import org.geysermc.common.PlatformType; import org.geysermc.geyser.GeyserBootstrap; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.command.Command; @@ -37,10 +36,11 @@ import org.geysermc.geyser.configuration.GeyserConfiguration; import org.geysermc.geyser.dump.BootstrapDumpInfo; import org.geysermc.geyser.ping.GeyserLegacyPingPassthrough; import org.geysermc.geyser.ping.IGeyserPingPassthrough; -import org.geysermc.geyser.platform.sponge.command.GeyserSpongeCommandManager; -import org.geysermc.geyser.util.FileUtils; -import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.platform.sponge.command.GeyserSpongeCommandExecutor; +import org.geysermc.geyser.platform.sponge.command.GeyserSpongeCommandManager; +import org.geysermc.geyser.text.GeyserLocale; +import org.geysermc.geyser.util.FileUtils; +import org.geysermc.geyser.util.PlatformType; import org.jetbrains.annotations.NotNull; import org.spongepowered.api.Server; import org.spongepowered.api.Sponge; @@ -142,7 +142,7 @@ public class GeyserSpongePlugin implements GeyserBootstrap { GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger); this.geyserLogger = new GeyserSpongeLogger(logger, geyserConfig.isDebugMode()); - this.geyser = GeyserImpl.load(PlatformType.SPONGE, this); + this.geyser = GeyserImpl.load(PlatformType.SPONGE, this, null); this.geyserCommandManager = new GeyserSpongeCommandManager(geyser); this.geyserCommandManager.init(); diff --git a/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneBootstrap.java b/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneBootstrap.java index c4271be4c..2445e016f 100644 --- a/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneBootstrap.java +++ b/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/GeyserStandaloneBootstrap.java @@ -38,7 +38,6 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.core.Appender; import org.apache.logging.log4j.core.Logger; import org.apache.logging.log4j.core.appender.ConsoleAppender; -import org.geysermc.common.PlatformType; import org.geysermc.geyser.GeyserBootstrap; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.command.GeyserCommandManager; @@ -51,6 +50,7 @@ import org.geysermc.geyser.platform.standalone.gui.GeyserStandaloneGUI; import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.util.FileUtils; import org.geysermc.geyser.util.LoopbackUtil; +import org.geysermc.geyser.util.PlatformType; import org.jetbrains.annotations.NotNull; import java.io.File; @@ -217,7 +217,7 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap { // Allow libraries like Protocol to have their debug information passthrough logger.get().setLevel(geyserConfig.isDebugMode() ? Level.DEBUG : Level.INFO); - geyser = GeyserImpl.load(PlatformType.STANDALONE, this); + geyser = GeyserImpl.load(PlatformType.STANDALONE, this, null); GeyserImpl.start(); geyserCommandManager = new GeyserCommandManager(geyser); diff --git a/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/gui/GeyserStandaloneGUI.java b/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/gui/GeyserStandaloneGUI.java index 41cbafb25..fed2f5a08 100644 --- a/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/gui/GeyserStandaloneGUI.java +++ b/bootstrap/standalone/src/main/java/org/geysermc/geyser/platform/standalone/gui/GeyserStandaloneGUI.java @@ -310,7 +310,7 @@ public class GeyserStandaloneGUI { for (GeyserSession player : GeyserImpl.getInstance().getSessionManager().getSessions().values()) { Vector row = new Vector<>(); - row.add(player.getSocketAddress().getHostName()); + row.add(player.socketAddress().getHostName()); row.add(player.getPlayerEntity().getUsername()); playerTableModel.addRow(row); diff --git a/bootstrap/velocity/build.gradle.kts b/bootstrap/velocity/build.gradle.kts index 8908b2afd..ae5d7f5b8 100644 --- a/bootstrap/velocity/build.gradle.kts +++ b/bootstrap/velocity/build.gradle.kts @@ -1,5 +1,6 @@ dependencies { annotationProcessor(libs.velocity.api) + implementation("org.geysermc.floodgate", "velocity", "2.2.0-SNAPSHOT") api(projects.core) } diff --git a/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPlugin.java b/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPlugin.java index 92b3a71a7..d88512b95 100644 --- a/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPlugin.java +++ b/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/GeyserVelocityPlugin.java @@ -26,6 +26,7 @@ package org.geysermc.geyser.platform.velocity; import com.google.inject.Inject; +import com.google.inject.Injector; import com.velocitypowered.api.command.CommandManager; import com.velocitypowered.api.event.Subscribe; import com.velocitypowered.api.event.proxy.ListenerBoundEvent; @@ -36,19 +37,22 @@ import com.velocitypowered.api.plugin.Plugin; import com.velocitypowered.api.proxy.ProxyServer; import lombok.Getter; import net.kyori.adventure.util.Codec; -import org.geysermc.common.PlatformType; +import org.geysermc.floodgate.FloodgatePlatform; import org.geysermc.geyser.GeyserBootstrap; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.command.Command; import org.geysermc.geyser.api.extension.Extension; +import org.geysermc.geyser.api.network.AuthType; import org.geysermc.geyser.command.GeyserCommandManager; import org.geysermc.geyser.configuration.GeyserConfiguration; import org.geysermc.geyser.dump.BootstrapDumpInfo; import org.geysermc.geyser.ping.GeyserLegacyPingPassthrough; import org.geysermc.geyser.ping.IGeyserPingPassthrough; import org.geysermc.geyser.platform.velocity.command.GeyserVelocityCommandExecutor; +import org.geysermc.geyser.platform.velocity.floodgate.FloodgateVelocityPlatform; import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.util.FileUtils; +import org.geysermc.geyser.util.PlatformType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; @@ -84,6 +88,9 @@ public class GeyserVelocityPlugin implements GeyserBootstrap { @Getter private final Path configFolder = Paths.get("plugins/" + GeyserImpl.NAME + "-Velocity/"); + @Inject + private Injector guice; + @Override public void onEnable() { try { @@ -113,7 +120,12 @@ public class GeyserVelocityPlugin implements GeyserBootstrap { this.geyserLogger = new GeyserVelocityLogger(logger, geyserConfig.isDebugMode()); GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger); - this.geyser = GeyserImpl.load(PlatformType.VELOCITY, this); + FloodgatePlatform platform = null; + if (geyserConfig.getRemote().authType() == AuthType.FLOODGATE) { + platform = guice.getInstance(FloodgateVelocityPlatform.class); + } + + this.geyser = GeyserImpl.load(PlatformType.VELOCITY, this, platform); // Remove this in like a year try { @@ -124,6 +136,19 @@ public class GeyserVelocityPlugin implements GeyserBootstrap { return; } catch (ClassNotFoundException ignored) { } + +// if (geyserConfig.getRemote().authType() == AuthType.FLOODGATE && proxyServer.getPluginManager().getPlugin("floodgate").isEmpty()) { +// geyserLogger.severe(GeyserLocale.getLocaleStringLog("geyser.bootstrap.floodgate.not_installed") + " " +// + GeyserLocale.getLocaleStringLog("geyser.bootstrap.floodgate.disabling")); +// return; +// } else if (geyserConfig.isAutoconfiguredRemote() && proxyServer.getPluginManager().getPlugin("floodgate").isPresent()) { +// // Floodgate installed means that the user wants Floodgate authentication +// geyserLogger.debug("Auto-setting to Floodgate authentication."); +// geyserConfig.getRemote().setAuthType(AuthType.FLOODGATE); +// } + + geyserConfig.loadFloodgate(this, proxyServer, configFolder.toFile()); + } private void postStartup() { diff --git a/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/floodgate/FloodgateVelocityPlatform.java b/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/floodgate/FloodgateVelocityPlatform.java new file mode 100644 index 000000000..e9ca5458c --- /dev/null +++ b/bootstrap/velocity/src/main/java/org/geysermc/geyser/platform/velocity/floodgate/FloodgateVelocityPlatform.java @@ -0,0 +1,46 @@ +/* + * 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.geyser.platform.velocity.floodgate; + +import com.google.inject.Module; +import org.geysermc.floodgate.VelocityPlatform; +import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.floodgate.GeyserLoadStage; + +import java.nio.file.Paths; +import java.util.List; + +public class FloodgateVelocityPlatform extends VelocityPlatform { + @Override + protected List loadStageModules() { + // Geyser being a dumb dumb + super.dataDirectory = Paths.get("plugins/" + GeyserImpl.NAME + "-Velocity/"); + + var loaded = super.loadStageModules(); + loaded.add(new GeyserLoadStage()); + return loaded; + } +} diff --git a/build.gradle.kts b/build.gradle.kts index 4304811ff..4ad2ee911 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -6,7 +6,7 @@ plugins { allprojects { group = "org.geysermc.geyser" - version = "2.1.0-SNAPSHOT" + version = "3.0.0-SNAPSHOT" description = "Allows for players from Minecraft: Bedrock Edition to join Minecraft: Java Edition servers." tasks.withType { diff --git a/core/build.gradle.kts b/core/build.gradle.kts index fd373baae..41426ae48 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -7,7 +7,7 @@ plugins { } dependencies { - api(projects.common) + api("org.geysermc.floodgate", "core", "2.2.0-SNAPSHOT") api(projects.api) // Jackson JSON and YAML serialization diff --git a/core/src/main/java/org/geysermc/connector/GeyserConnector.java b/core/src/main/java/org/geysermc/connector/GeyserConnector.java index 2616b91d3..7e7a20672 100644 --- a/core/src/main/java/org/geysermc/connector/GeyserConnector.java +++ b/core/src/main/java/org/geysermc/connector/GeyserConnector.java @@ -26,9 +26,9 @@ package org.geysermc.connector; import org.geysermc.api.Geyser; -import org.geysermc.common.PlatformType; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.util.PlatformType; import java.util.UUID; diff --git a/core/src/main/java/org/geysermc/geyser/GeyserBootstrap.java b/core/src/main/java/org/geysermc/geyser/GeyserBootstrap.java index e4baeebb5..57fe99c9d 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserBootstrap.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserBootstrap.java @@ -25,9 +25,12 @@ package org.geysermc.geyser; +import org.geysermc.floodgate.skin.SkinApplier; import org.geysermc.geyser.command.GeyserCommandManager; import org.geysermc.geyser.configuration.GeyserConfiguration; import org.geysermc.geyser.dump.BootstrapDumpInfo; +import org.geysermc.geyser.hybrid.FloodgateHybridProvider; +import org.geysermc.geyser.hybrid.HybridProvider; import org.geysermc.geyser.level.GeyserWorldManager; import org.geysermc.geyser.level.WorldManager; import org.geysermc.geyser.ping.IGeyserPingPassthrough; @@ -134,6 +137,20 @@ public interface GeyserBootstrap { return Paths.get("logs/latest.log"); } + /** + * Creates the hybrid provider for this platform. The provider will differ based on server access. + */ + default HybridProvider createHybridProvider(GeyserImpl geyser) { + return new FloodgateHybridProvider(geyser); + } + + /** + * Returns the skin applier for this platform, if the hybrid provider is integrated with the system. + */ + default SkinApplier createSkinApplier() { + throw new IllegalStateException(); + } + /** * Get an InputStream for the given resource path. * Overridden on platforms that have different class loader properties. diff --git a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java index 45321163b..bbf0bc578 100644 --- a/core/src/main/java/org/geysermc/geyser/GeyserImpl.java +++ b/core/src/main/java/org/geysermc/geyser/GeyserImpl.java @@ -43,14 +43,10 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.geysermc.api.Geyser; -import org.geysermc.common.PlatformType; import org.geysermc.cumulus.form.Form; import org.geysermc.cumulus.form.util.FormBuilder; import org.geysermc.erosion.packet.Packets; -import org.geysermc.floodgate.crypto.AesCipher; -import org.geysermc.floodgate.crypto.AesKeyProducer; -import org.geysermc.floodgate.crypto.Base64Topping; -import org.geysermc.floodgate.crypto.FloodgateCipher; +import org.geysermc.floodgate.FloodgatePlatform; import org.geysermc.floodgate.news.NewsItemAction; import org.geysermc.geyser.api.GeyserApi; import org.geysermc.geyser.api.event.EventBus; @@ -67,6 +63,7 @@ import org.geysermc.geyser.entity.EntityDefinitions; import org.geysermc.geyser.erosion.UnixSocketClientListener; import org.geysermc.geyser.event.GeyserEventBus; import org.geysermc.geyser.extension.GeyserExtensionManager; +import org.geysermc.geyser.hybrid.HybridProvider; import org.geysermc.geyser.level.WorldManager; import org.geysermc.geyser.network.netty.GeyserServer; import org.geysermc.geyser.pack.ResourcePack; @@ -76,7 +73,7 @@ import org.geysermc.geyser.scoreboard.ScoreboardUpdater; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.PendingMicrosoftAuthentication; import org.geysermc.geyser.session.SessionManager; -import org.geysermc.geyser.skin.FloodgateSkinUploader; +import org.geysermc.geyser.skin.BedrockSkinUploader; import org.geysermc.geyser.skin.ProvidedSkins; import org.geysermc.geyser.skin.SkinProvider; import org.geysermc.geyser.text.GeyserLocale; @@ -90,7 +87,6 @@ import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.UnknownHostException; -import java.security.Key; import java.text.DecimalFormat; import java.util.*; import java.util.concurrent.CompletableFuture; @@ -133,8 +129,8 @@ public class GeyserImpl implements GeyserApi { @Setter private static boolean shouldStartListener = true; - private FloodgateCipher cipher; - private FloodgateSkinUploader skinUploader; + private HybridProvider hybridProvider; + private BedrockSkinUploader skinUploader; private NewsHandler newsHandler; private UnixSocketClientListener erosionUnixListener; @@ -158,10 +154,18 @@ public class GeyserImpl implements GeyserApi { private static GeyserImpl instance; - private GeyserImpl(PlatformType platformType, GeyserBootstrap bootstrap) { - instance = this; + private final FloodgatePlatform floodgatePlatform; - Geyser.set(this); + private GeyserImpl(PlatformType platformType, GeyserBootstrap bootstrap, FloodgatePlatform floodgatePlatform) { + instance = this; + this.floodgatePlatform = floodgatePlatform; + + if (floodgatePlatform != null) { + floodgatePlatform.load(); + floodgatePlatform.enable(); + } else { + Geyser.set(this); + } this.platformType = platformType; this.bootstrap = bootstrap; @@ -259,7 +263,7 @@ public class GeyserImpl implements GeyserApi { SkinProvider.registerCacheImageTask(this); ResourcePack.loadPacks(); - + //TODO start String geyserUdpPort = System.getProperty("geyserUdpPort", ""); String pluginUdpPort = geyserUdpPort.isEmpty() ? System.getProperty("pluginUdpPort", "") : geyserUdpPort; if ("-1".equals(pluginUdpPort)) { @@ -335,6 +339,7 @@ public class GeyserImpl implements GeyserApi { config.getRemote().setAuthType(AuthType.FLOODGATE); } } + //TODO end String remoteAddress = config.getRemote().address(); // Filters whether it is not an IP address or localhost, because otherwise it is not possible to find out an SRV entry. @@ -392,16 +397,14 @@ public class GeyserImpl implements GeyserApi { } if (config.getRemote().authType() == AuthType.FLOODGATE) { + hybridProvider = bootstrap.createHybridProvider(this); try { - Key key = new AesKeyProducer().produceFrom(config.getFloodgateKeyPath()); - cipher = new AesCipher(new Base64Topping()); - cipher.init(key); - logger.debug("Loaded Floodgate key!"); // Note: this is positioned after the bind so the skin uploader doesn't try to run if Geyser fails // to load successfully. Spigot complains about class loader if the plugin is disabled. - skinUploader = new FloodgateSkinUploader(this).start(); + // TODO not Floodgate exclusive? + skinUploader = new BedrockSkinUploader(this).start(); } catch (Exception exception) { - logger.severe(GeyserLocale.getLocaleStringLog("geyser.auth.floodgate.bad_key"), exception); + logger.severe("Could not start the skin uploader!", exception); } } @@ -687,9 +690,9 @@ public class GeyserImpl implements GeyserApi { return Integer.parseInt(BUILD_NUMBER); } - public static GeyserImpl load(PlatformType platformType, GeyserBootstrap bootstrap) { + public static GeyserImpl load(PlatformType platformType, GeyserBootstrap bootstrap, FloodgatePlatform floodgatePlatform) { if (instance == null) { - return new GeyserImpl(platformType, bootstrap); + return new GeyserImpl(platformType, bootstrap, floodgatePlatform); } return instance; diff --git a/core/src/main/java/org/geysermc/geyser/command/GeyserCommandManager.java b/core/src/main/java/org/geysermc/geyser/command/GeyserCommandManager.java index d28f9d24e..86f26bed4 100644 --- a/core/src/main/java/org/geysermc/geyser/command/GeyserCommandManager.java +++ b/core/src/main/java/org/geysermc/geyser/command/GeyserCommandManager.java @@ -29,38 +29,22 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import lombok.Getter; import lombok.RequiredArgsConstructor; import org.checkerframework.checker.nullness.qual.NonNull; -import org.geysermc.common.PlatformType; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.command.Command; import org.geysermc.geyser.api.command.CommandExecutor; import org.geysermc.geyser.api.command.CommandSource; import org.geysermc.geyser.api.event.lifecycle.GeyserDefineCommandsEvent; import org.geysermc.geyser.api.extension.Extension; -import org.geysermc.geyser.command.defaults.AdvancedTooltipsCommand; -import org.geysermc.geyser.command.defaults.AdvancementsCommand; -import org.geysermc.geyser.command.defaults.ConnectionTestCommand; -import org.geysermc.geyser.command.defaults.DumpCommand; -import org.geysermc.geyser.command.defaults.ExtensionsCommand; -import org.geysermc.geyser.command.defaults.HelpCommand; -import org.geysermc.geyser.command.defaults.ListCommand; -import org.geysermc.geyser.command.defaults.OffhandCommand; -import org.geysermc.geyser.command.defaults.ReloadCommand; -import org.geysermc.geyser.command.defaults.SettingsCommand; -import org.geysermc.geyser.command.defaults.StatisticsCommand; -import org.geysermc.geyser.command.defaults.StopCommand; -import org.geysermc.geyser.command.defaults.VersionCommand; +import org.geysermc.geyser.command.defaults.*; import org.geysermc.geyser.event.type.GeyserDefineCommandsEventImpl; import org.geysermc.geyser.extension.command.GeyserExtensionCommand; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.GeyserLocale; +import org.geysermc.geyser.util.PlatformType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; +import java.util.*; @RequiredArgsConstructor public class GeyserCommandManager { diff --git a/core/src/main/java/org/geysermc/geyser/command/defaults/ConnectionTestCommand.java b/core/src/main/java/org/geysermc/geyser/command/defaults/ConnectionTestCommand.java index 95c115769..6c381ad4b 100644 --- a/core/src/main/java/org/geysermc/geyser/command/defaults/ConnectionTestCommand.java +++ b/core/src/main/java/org/geysermc/geyser/command/defaults/ConnectionTestCommand.java @@ -26,13 +26,13 @@ package org.geysermc.geyser.command.defaults; import com.fasterxml.jackson.databind.JsonNode; -import org.geysermc.common.PlatformType; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.command.GeyserCommand; import org.geysermc.geyser.command.GeyserCommandSource; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.util.LoopbackUtil; +import org.geysermc.geyser.util.PlatformType; import org.geysermc.geyser.util.WebUtils; import org.jetbrains.annotations.Nullable; diff --git a/core/src/main/java/org/geysermc/geyser/command/defaults/DumpCommand.java b/core/src/main/java/org/geysermc/geyser/command/defaults/DumpCommand.java index 60683d34a..0aa7f8445 100644 --- a/core/src/main/java/org/geysermc/geyser/command/defaults/DumpCommand.java +++ b/core/src/main/java/org/geysermc/geyser/command/defaults/DumpCommand.java @@ -30,7 +30,6 @@ import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import org.checkerframework.checker.nullness.qual.NonNull; -import org.geysermc.common.PlatformType; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.command.GeyserCommand; import org.geysermc.geyser.command.GeyserCommandSource; @@ -39,6 +38,7 @@ import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.AsteriskSerializer; import org.geysermc.geyser.text.ChatColor; import org.geysermc.geyser.text.GeyserLocale; +import org.geysermc.geyser.util.PlatformType; import org.geysermc.geyser.util.WebUtils; import java.io.FileOutputStream; diff --git a/core/src/main/java/org/geysermc/geyser/command/defaults/HelpCommand.java b/core/src/main/java/org/geysermc/geyser/command/defaults/HelpCommand.java index 6e7ad2f04..5308ac162 100644 --- a/core/src/main/java/org/geysermc/geyser/command/defaults/HelpCommand.java +++ b/core/src/main/java/org/geysermc/geyser/command/defaults/HelpCommand.java @@ -25,7 +25,6 @@ package org.geysermc.geyser.command.defaults; -import org.geysermc.common.PlatformType; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.command.Command; import org.geysermc.geyser.command.GeyserCommand; @@ -33,6 +32,7 @@ import org.geysermc.geyser.command.GeyserCommandSource; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.ChatColor; import org.geysermc.geyser.text.GeyserLocale; +import org.geysermc.geyser.util.PlatformType; import java.util.Collections; import java.util.Map; diff --git a/core/src/main/java/org/geysermc/geyser/command/defaults/ReloadCommand.java b/core/src/main/java/org/geysermc/geyser/command/defaults/ReloadCommand.java index 843e93de0..2820e6677 100644 --- a/core/src/main/java/org/geysermc/geyser/command/defaults/ReloadCommand.java +++ b/core/src/main/java/org/geysermc/geyser/command/defaults/ReloadCommand.java @@ -25,12 +25,12 @@ package org.geysermc.geyser.command.defaults; -import org.geysermc.common.PlatformType; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.command.GeyserCommand; import org.geysermc.geyser.command.GeyserCommandSource; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.GeyserLocale; +import org.geysermc.geyser.util.PlatformType; public class ReloadCommand extends GeyserCommand { diff --git a/core/src/main/java/org/geysermc/geyser/command/defaults/StopCommand.java b/core/src/main/java/org/geysermc/geyser/command/defaults/StopCommand.java index 151aa2d84..19ce88dea 100644 --- a/core/src/main/java/org/geysermc/geyser/command/defaults/StopCommand.java +++ b/core/src/main/java/org/geysermc/geyser/command/defaults/StopCommand.java @@ -25,12 +25,12 @@ package org.geysermc.geyser.command.defaults; -import org.geysermc.common.PlatformType; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.command.GeyserCommand; import org.geysermc.geyser.command.GeyserCommandSource; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.GeyserLocale; +import org.geysermc.geyser.util.PlatformType; import java.util.Collections; diff --git a/core/src/main/java/org/geysermc/geyser/command/defaults/VersionCommand.java b/core/src/main/java/org/geysermc/geyser/command/defaults/VersionCommand.java index b2b5d54a3..d844b6c8f 100644 --- a/core/src/main/java/org/geysermc/geyser/command/defaults/VersionCommand.java +++ b/core/src/main/java/org/geysermc/geyser/command/defaults/VersionCommand.java @@ -26,7 +26,6 @@ package org.geysermc.geyser.command.defaults; import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec; -import org.geysermc.common.PlatformType; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.command.GeyserCommand; import org.geysermc.geyser.command.GeyserCommandSource; @@ -34,6 +33,7 @@ import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.ChatColor; import org.geysermc.geyser.text.GeyserLocale; +import org.geysermc.geyser.util.PlatformType; import org.geysermc.geyser.util.WebUtils; import java.io.IOException; diff --git a/core/src/main/java/org/geysermc/geyser/configuration/GeyserConfiguration.java b/core/src/main/java/org/geysermc/geyser/configuration/GeyserConfiguration.java index 222af341b..6ff7f5fb2 100644 --- a/core/src/main/java/org/geysermc/geyser/configuration/GeyserConfiguration.java +++ b/core/src/main/java/org/geysermc/geyser/configuration/GeyserConfiguration.java @@ -51,6 +51,8 @@ public interface GeyserConfiguration { IRemoteConfiguration getRemote(); + HybridInfo getHybridInfo(); + List getSavedUserLogins(); @Deprecated @@ -164,6 +166,13 @@ public interface GeyserConfiguration { void setAuthType(AuthType authType); } + // TODO this is definitely temporary + interface HybridInfo { + String usernamePrefix(); + + boolean replaceSpaces(); + } + interface IUserAuthenticationInfo { String getEmail(); diff --git a/core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java b/core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java index e096d58fa..6dfd397e1 100644 --- a/core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java +++ b/core/src/main/java/org/geysermc/geyser/configuration/GeyserJacksonConfiguration.java @@ -59,6 +59,18 @@ public abstract class GeyserJacksonConfiguration implements GeyserConfiguration private BedrockConfiguration bedrock = new BedrockConfiguration(); private RemoteConfiguration remote = new RemoteConfiguration(); + private HybridInfo hybridInfo = new HybridInfo() { + @Override + public String usernamePrefix() { + return "."; + } + + @Override + public boolean replaceSpaces() { + return true; + } + }; + @JsonProperty("saved-user-logins") private List savedUserLogins = Collections.emptyList(); diff --git a/core/src/main/java/org/geysermc/geyser/dump/BootstrapDumpInfo.java b/core/src/main/java/org/geysermc/geyser/dump/BootstrapDumpInfo.java index fda0566fd..1e97af527 100644 --- a/core/src/main/java/org/geysermc/geyser/dump/BootstrapDumpInfo.java +++ b/core/src/main/java/org/geysermc/geyser/dump/BootstrapDumpInfo.java @@ -27,9 +27,9 @@ package org.geysermc.geyser.dump; import lombok.AllArgsConstructor; import lombok.Getter; -import org.geysermc.common.PlatformType; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.text.AsteriskSerializer; +import org.geysermc.geyser.util.PlatformType; import java.util.List; diff --git a/core/src/main/java/org/geysermc/geyser/dump/DumpInfo.java b/core/src/main/java/org/geysermc/geyser/dump/DumpInfo.java index 290a0e3ad..22e02d0cf 100644 --- a/core/src/main/java/org/geysermc/geyser/dump/DumpInfo.java +++ b/core/src/main/java/org/geysermc/geyser/dump/DumpInfo.java @@ -36,8 +36,7 @@ import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import lombok.AllArgsConstructor; import lombok.Getter; import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec; -import org.geysermc.floodgate.util.DeviceOs; -import org.geysermc.floodgate.util.FloodgateInfoHolder; +import org.geysermc.api.util.BedrockPlatform; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.api.GeyserApi; import org.geysermc.geyser.api.extension.Extension; @@ -78,7 +77,7 @@ public class DumpInfo { private final GitInfo gitInfo; private final GeyserConfiguration config; private final Floodgate floodgate; - private final Object2IntMap userPlatforms; + private final Object2IntMap userPlatforms; private final HashInfo hashInfo; private final RamInfo ramInfo; private LogsInfo logsInfo; @@ -126,7 +125,7 @@ public class DumpInfo { this.userPlatforms = new Object2IntOpenHashMap<>(); for (GeyserSession session : GeyserImpl.getInstance().getSessionManager().getAllSessions()) { - DeviceOs device = session.getClientData().getDeviceOs(); + BedrockPlatform device = session.getClientData().getDeviceOs(); userPlatforms.put(device, userPlatforms.getOrDefault(device, 0) + 1); } @@ -238,8 +237,11 @@ public class DumpInfo { private final Object config; Floodgate() { - this.gitInfo = FloodgateInfoHolder.getGitProperties(); - this.config = FloodgateInfoHolder.getConfig(); + //todo we can get the information from Floodgate directly now + this.gitInfo = null; + this.config = null; +// this.gitInfo = FloodgateInfoHolder.getGitProperties(); +// this.config = FloodgateInfoHolder.getConfig(); } } diff --git a/core/src/main/java/org/geysermc/geyser/entity/type/FireworkEntity.java b/core/src/main/java/org/geysermc/geyser/entity/type/FireworkEntity.java index 7a544f23c..9e5054e05 100644 --- a/core/src/main/java/org/geysermc/geyser/entity/type/FireworkEntity.java +++ b/core/src/main/java/org/geysermc/geyser/entity/type/FireworkEntity.java @@ -36,7 +36,6 @@ import org.cloudburstmc.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtType; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.packet.SetEntityMotionPacket; -import org.geysermc.floodgate.util.DeviceOs; import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.type.player.PlayerEntity; import org.geysermc.geyser.level.FireworkColor; @@ -65,13 +64,6 @@ public class FireworkEntity extends Entity { return; } - // TODO: Remove once Mojang fixes bugs with fireworks crashing clients on these specific devices. - // https://bugs.mojang.com/browse/MCPE-89115 - if (session.getClientData().getDeviceOs() == DeviceOs.XBOX - || session.getClientData().getDeviceOs() == DeviceOs.PS4) { - return; - } - CompoundTag fireworks = tag.get("Fireworks"); if (fireworks == null) { // Thank you Mineplex very cool diff --git a/common/src/main/java/org/geysermc/floodgate/util/UiProfile.java b/core/src/main/java/org/geysermc/geyser/floodgate/GeyserLoadStage.java similarity index 73% rename from common/src/main/java/org/geysermc/floodgate/util/UiProfile.java rename to core/src/main/java/org/geysermc/geyser/floodgate/GeyserLoadStage.java index d93042277..f0551f76e 100644 --- a/common/src/main/java/org/geysermc/floodgate/util/UiProfile.java +++ b/core/src/main/java/org/geysermc/geyser/floodgate/GeyserLoadStage.java @@ -23,21 +23,18 @@ * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.floodgate.util; +package org.geysermc.geyser.floodgate; -public enum UiProfile { - CLASSIC, - POCKET; +import com.google.inject.AbstractModule; +import com.google.inject.Provides; +import com.google.inject.Singleton; +import com.google.inject.name.Named; - private static final UiProfile[] VALUES = values(); - - /** - * Get the UiProfile instance from the identifier. - * - * @param id the UiProfile identifier - * @return The UiProfile or {@link #CLASSIC} if the UiProfile wasn't found - */ - public static UiProfile fromId(int id) { - return VALUES.length > id ? VALUES[id] : VALUES[0]; +public class GeyserLoadStage extends AbstractModule { + @Provides + @Singleton + @Named("configFile") + private String floodgateConfigName() { + return "floodgate.yml"; } } diff --git a/common/src/main/java/org/geysermc/floodgate/util/DeviceOs.java b/core/src/main/java/org/geysermc/geyser/hybrid/FloodgateHybridProvider.java similarity index 52% rename from common/src/main/java/org/geysermc/floodgate/util/DeviceOs.java rename to core/src/main/java/org/geysermc/geyser/hybrid/FloodgateHybridProvider.java index 406204759..f67d95a09 100644 --- a/common/src/main/java/org/geysermc/floodgate/util/DeviceOs.java +++ b/core/src/main/java/org/geysermc/geyser/hybrid/FloodgateHybridProvider.java @@ -23,51 +23,31 @@ * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.floodgate.util; +package org.geysermc.geyser.hybrid; -import lombok.AccessLevel; -import lombok.RequiredArgsConstructor; +import org.geysermc.floodgate.crypto.FloodgateCipher; +import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.session.GeyserSession; -/** - * The Operation Systems where Bedrock players can connect with - */ -@RequiredArgsConstructor(access = AccessLevel.PRIVATE) -public enum DeviceOs { - UNKNOWN("Unknown"), - GOOGLE("Android"), - IOS("iOS"), - OSX("macOS"), - AMAZON("Amazon"), - GEARVR("Gear VR"), - HOLOLENS("Hololens"), - UWP("Windows"), - WIN32("Windows x86"), - DEDICATED("Dedicated"), - TVOS("Apple TV"), - PS4("PS4"), - NX("Switch"), - XBOX("Xbox One"), - WINDOWS_PHONE("Windows Phone"); +import java.nio.charset.StandardCharsets; - private static final DeviceOs[] VALUES = values(); +public final class FloodgateHybridProvider implements HybridProvider { + private final FloodgateCipher cipher; - private final String displayName; - - /** - * Get the DeviceOs instance from the identifier. - * - * @param id the DeviceOs identifier - * @return The DeviceOs or {@link #UNKNOWN} if the DeviceOs wasn't found - */ - public static DeviceOs fromId(int id) { - return id < VALUES.length ? VALUES[id] : VALUES[0]; + public FloodgateHybridProvider(GeyserImpl geyser) { + cipher = geyser.getFloodgatePlatform().getInstance(FloodgateCipher.class); } - /** - * @return friendly display name of platform. - */ @Override - public String toString() { - return displayName; + public void onSkinUpload(GeyserSession session, String value, String signature) { + byte[] bytes = (value + '\0' + signature) + .getBytes(StandardCharsets.UTF_8); + //todo +// PluginMessageUtils.sendMessage(session, PluginMessageChannels.SKIN, bytes); } -} \ No newline at end of file + + @Override + public FloodgateCipher getCipher() { + return cipher; + } +} diff --git a/core/src/main/java/org/geysermc/geyser/hybrid/HybridProvider.java b/core/src/main/java/org/geysermc/geyser/hybrid/HybridProvider.java new file mode 100644 index 000000000..e84f81cb1 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/hybrid/HybridProvider.java @@ -0,0 +1,35 @@ +/* + * 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.geyser.hybrid; + +import org.geysermc.floodgate.crypto.FloodgateCipher; +import org.geysermc.geyser.session.GeyserSession; + +public interface HybridProvider { + void onSkinUpload(GeyserSession session, String value, String signature); + + FloodgateCipher getCipher(); +} diff --git a/core/src/main/java/org/geysermc/geyser/hybrid/IntegratedHybridProvider.java b/core/src/main/java/org/geysermc/geyser/hybrid/IntegratedHybridProvider.java new file mode 100644 index 000000000..6b4dff7a5 --- /dev/null +++ b/core/src/main/java/org/geysermc/geyser/hybrid/IntegratedHybridProvider.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2019-2021 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.geyser.hybrid; + +import io.netty.util.AttributeKey; +import org.geysermc.floodgate.crypto.FloodgateCipher; +import org.geysermc.floodgate.skin.SkinApplier; +import org.geysermc.floodgate.skin.SkinData; +import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.session.GeyserSession; + +public class IntegratedHybridProvider implements HybridProvider { + // TODO This will probably end up as its own class. + public static final AttributeKey SESSION_KEY = AttributeKey.valueOf("geyser-session"); + + private final SkinApplier skinApplier; + + public IntegratedHybridProvider(GeyserImpl geyser) { + skinApplier = geyser.getBootstrap().createSkinApplier(); + } + + @Override + public void onSkinUpload(GeyserSession session, String value, String signature) { + skinApplier.applySkin(session, new SkinData(value, signature)); + } + + @Override + public FloodgateCipher getCipher() { + throw new UnsupportedOperationException(); + } +} diff --git a/common/src/main/java/org/geysermc/floodgate/util/InputMode.java b/core/src/main/java/org/geysermc/geyser/hybrid/ProxyHybridProvider.java similarity index 71% rename from common/src/main/java/org/geysermc/floodgate/util/InputMode.java rename to core/src/main/java/org/geysermc/geyser/hybrid/ProxyHybridProvider.java index 2bcfb88fb..0bc9d9d50 100644 --- a/common/src/main/java/org/geysermc/floodgate/util/InputMode.java +++ b/core/src/main/java/org/geysermc/geyser/hybrid/ProxyHybridProvider.java @@ -23,24 +23,21 @@ * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.floodgate.util; +package org.geysermc.geyser.hybrid; -public enum InputMode { - UNKNOWN, - KEYBOARD_MOUSE, - TOUCH, - CONTROLLER, - VR; +import org.geysermc.floodgate.crypto.FloodgateCipher; +import org.geysermc.geyser.GeyserImpl; - private static final InputMode[] VALUES = values(); +public final class ProxyHybridProvider extends IntegratedHybridProvider { + private final FloodgateCipher cipher; - /** - * Get the InputMode instance from the identifier. - * - * @param id the InputMode identifier - * @return The InputMode or {@link #UNKNOWN} if the DeviceOs wasn't found - */ - public static InputMode fromId(int id) { - return VALUES.length > id ? VALUES[id] : VALUES[0]; + public ProxyHybridProvider(GeyserImpl geyser) { + super(geyser); + this.cipher = geyser.getFloodgatePlatform().getInstance(FloodgateCipher.class); } -} \ No newline at end of file + + @Override + public FloodgateCipher getCipher() { + return cipher; + } +} diff --git a/core/src/main/java/org/geysermc/geyser/network/netty/LocalServerChannelWrapper.java b/core/src/main/java/org/geysermc/geyser/network/netty/LocalServerChannelWrapper.java index bb8ca754f..b91653611 100644 --- a/core/src/main/java/org/geysermc/geyser/network/netty/LocalServerChannelWrapper.java +++ b/core/src/main/java/org/geysermc/geyser/network/netty/LocalServerChannelWrapper.java @@ -27,6 +27,10 @@ package org.geysermc.geyser.network.netty; import io.netty.channel.local.LocalChannel; import io.netty.channel.local.LocalServerChannel; +import io.netty.util.Attribute; +import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.hybrid.IntegratedHybridProvider; +import org.geysermc.geyser.session.GeyserSession; /** * If the incoming channel if an instance of LocalChannelWithRemoteAddress, this server creates a LocalChannelWrapper @@ -36,9 +40,17 @@ public class LocalServerChannelWrapper extends LocalServerChannel { @Override protected LocalChannel newLocalChannel(LocalChannel peer) { // LocalChannel here should be an instance of LocalChannelWithRemoteAddress, which we can use to set the "remote address" on the other end - if (peer instanceof LocalChannelWithRemoteAddress) { + if (peer instanceof LocalChannelWithRemoteAddress) { // TODO also use attribute for this LocalChannelWrapper channel = new LocalChannelWrapper(this, peer); channel.wrapper().remoteAddress(((LocalChannelWithRemoteAddress) peer).spoofedRemoteAddress()); + + if (GeyserImpl.getInstance().getHybridProvider() instanceof IntegratedHybridProvider) { + Attribute attribute = peer.attr(IntegratedHybridProvider.SESSION_KEY); + GeyserSession session = attribute.get(); + // Garbage collect since it's no longer relevant for the PacketLib side. + attribute.set(null); + channel.attr(IntegratedHybridProvider.SESSION_KEY).set(session); + } return channel; } return super.newLocalChannel(peer); diff --git a/core/src/main/java/org/geysermc/geyser/network/netty/LocalSession.java b/core/src/main/java/org/geysermc/geyser/network/netty/LocalSession.java index 551bc1deb..ce02b5af8 100644 --- a/core/src/main/java/org/geysermc/geyser/network/netty/LocalSession.java +++ b/core/src/main/java/org/geysermc/geyser/network/netty/LocalSession.java @@ -37,7 +37,12 @@ import io.netty.buffer.ByteBufAllocator; import io.netty.channel.*; import io.netty.channel.unix.PreferredDirectByteBufAllocator; import io.netty.handler.codec.haproxy.*; +import io.netty.util.Attribute; +import org.geysermc.geyser.GeyserImpl; +import org.geysermc.geyser.hybrid.IntegratedHybridProvider; +import org.geysermc.geyser.session.GeyserSession; +import javax.annotation.Nullable; import java.net.Inet4Address; import java.net.InetSocketAddress; import java.net.SocketAddress; @@ -53,11 +58,14 @@ public final class LocalSession extends TcpSession { private final String clientIp; private final PacketCodecHelper codecHelper; - public LocalSession(String host, int port, SocketAddress targetAddress, String clientIp, PacketProtocol protocol, MinecraftCodecHelper codecHelper) { + private final GeyserSession session; + + public LocalSession(@Nullable GeyserSession session, String host, int port, SocketAddress targetAddress, String clientIp, PacketProtocol protocol, MinecraftCodecHelper codecHelper) { super(host, port, protocol); this.targetAddress = targetAddress; this.clientIp = clientIp; this.codecHelper = codecHelper; + this.session = session; } @Override @@ -89,6 +97,11 @@ public final class LocalSession extends TcpSession { pipeline.addLast("manager", LocalSession.this); addHAProxySupport(pipeline); + + if (GeyserImpl.getInstance().getHybridProvider() instanceof IntegratedHybridProvider) { + Attribute attribute = channel.attr(IntegratedHybridProvider.SESSION_KEY); + attribute.set(session); + } } }).group(DEFAULT_EVENT_LOOP_GROUP).option(ChannelOption.CONNECT_TIMEOUT_MILLIS, getConnectTimeout() * 1000); diff --git a/core/src/main/java/org/geysermc/geyser/registry/PacketTranslatorRegistry.java b/core/src/main/java/org/geysermc/geyser/registry/PacketTranslatorRegistry.java index 0acfeee93..8cd1ee718 100644 --- a/core/src/main/java/org/geysermc/geyser/registry/PacketTranslatorRegistry.java +++ b/core/src/main/java/org/geysermc/geyser/registry/PacketTranslatorRegistry.java @@ -33,6 +33,7 @@ import org.geysermc.geyser.registry.loader.RegistryLoaders; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.translator.protocol.PacketTranslator; +import org.geysermc.geyser.util.PlatformType; import java.util.Collections; import java.util.IdentityHashMap; diff --git a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java index e841dd43c..b5da237fd 100644 --- a/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java +++ b/core/src/main/java/org/geysermc/geyser/session/GeyserSession.java @@ -94,7 +94,6 @@ import org.cloudburstmc.protocol.common.util.OptionalBoolean; import org.geysermc.api.util.BedrockPlatform; import org.geysermc.api.util.InputMode; import org.geysermc.api.util.UiProfile; -import org.geysermc.common.PlatformType; import org.geysermc.cumulus.form.Form; import org.geysermc.cumulus.form.util.FormBuilder; import org.geysermc.floodgate.crypto.FloodgateCipher; @@ -116,6 +115,8 @@ import org.geysermc.geyser.entity.type.Tickable; import org.geysermc.geyser.entity.type.player.SessionPlayerEntity; import org.geysermc.geyser.erosion.AbstractGeyserboundPacketHandler; import org.geysermc.geyser.erosion.GeyserboundHandshakePacketHandler; +import org.geysermc.geyser.hybrid.FloodgateHybridProvider; +import org.geysermc.geyser.hybrid.HybridProvider; import org.geysermc.geyser.inventory.Inventory; import org.geysermc.geyser.inventory.PlayerInventory; import org.geysermc.geyser.inventory.recipe.GeyserRecipe; @@ -131,15 +132,13 @@ import org.geysermc.geyser.registry.type.ItemMappings; import org.geysermc.geyser.session.auth.AuthData; import org.geysermc.geyser.session.auth.BedrockClientData; import org.geysermc.geyser.session.cache.*; -import org.geysermc.geyser.skin.FloodgateSkinUploader; +import org.geysermc.geyser.skin.BedrockSkinUploader; import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.text.MinecraftLocale; import org.geysermc.geyser.text.TextDecoration; import org.geysermc.geyser.translator.inventory.InventoryTranslator; import org.geysermc.geyser.translator.text.MessageTranslator; -import org.geysermc.geyser.util.ChunkUtils; -import org.geysermc.geyser.util.DimensionUtils; -import org.geysermc.geyser.util.LoginEncryptionUtils; +import org.geysermc.geyser.util.*; import org.jetbrains.annotations.NotNull; import java.net.ConnectException; @@ -886,7 +885,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { TcpSession downstream; if (geyser.getBootstrap().getSocketAddress() != null) { // We're going to connect through the JVM and not through TCP - downstream = new LocalSession(this.remoteServer.address(), this.remoteServer.port(), + downstream = new LocalSession(this, this.remoteServer.address(), this.remoteServer.port(), geyser.getBootstrap().getSocketAddress(), upstream.getAddress().getAddress().getHostAddress(), this.protocol, this.protocol.createHelper()); this.downstream = new DownstreamSession(downstream); @@ -910,12 +909,13 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { //todo move this somewhere else if (event.getPacket() instanceof ClientIntentionPacket) { String addressSuffix; - if (floodgate) { + HybridProvider provider; + if (floodgate && (provider = geyser.getHybridProvider()) instanceof FloodgateHybridProvider) { byte[] encryptedData; try { - FloodgateSkinUploader skinUploader = geyser.getSkinUploader(); - FloodgateCipher cipher = geyser.getCipher(); + BedrockSkinUploader skinUploader = geyser.getSkinUploader(); + FloodgateCipher cipher = provider.getCipher(); String bedrockAddress = upstream.getAddress().getAddress().getHostAddress(); // both BungeeCord and Velocity remove the IPv6 scope (if there is one) for Spigot @@ -1434,7 +1434,8 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { upstream.sendPacket(chunkRadiusUpdatedPacket); } - public InetSocketAddress getSocketAddress() { + @Override + public InetSocketAddress socketAddress() { return this.upstream.getAddress(); } @@ -1885,7 +1886,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { @Override public @NonNull BedrockPlatform platform() { - return BedrockPlatform.values()[clientData.getDeviceOs().ordinal()]; //todo + return clientData.getDeviceOs(); } @Override @@ -1895,12 +1896,12 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource { @Override public @NonNull UiProfile uiProfile() { - return UiProfile.values()[clientData.getUiProfile().ordinal()]; //todo + return clientData.getUiProfile(); } @Override public @NonNull InputMode inputMode() { - return InputMode.values()[clientData.getCurrentInputMode().ordinal()]; //todo + return clientData.getCurrentInputMode(); } @Override diff --git a/core/src/main/java/org/geysermc/geyser/session/auth/BedrockClientData.java b/core/src/main/java/org/geysermc/geyser/session/auth/BedrockClientData.java index 07dd38491..4ce8d555e 100644 --- a/core/src/main/java/org/geysermc/geyser/session/auth/BedrockClientData.java +++ b/core/src/main/java/org/geysermc/geyser/session/auth/BedrockClientData.java @@ -30,9 +30,9 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; import lombok.Setter; -import org.geysermc.floodgate.util.DeviceOs; -import org.geysermc.floodgate.util.InputMode; -import org.geysermc.floodgate.util.UiProfile; +import org.geysermc.api.util.BedrockPlatform; +import org.geysermc.api.util.InputMode; +import org.geysermc.api.util.UiProfile; import java.util.UUID; @@ -80,7 +80,7 @@ public final class BedrockClientData { @JsonProperty(value = "DeviceModel") private String deviceModel; @JsonProperty(value = "DeviceOS") - private DeviceOs deviceOs; + private BedrockPlatform deviceOs; @JsonProperty(value = "UIProfile") private UiProfile uiProfile; @JsonProperty(value = "GuiScale") @@ -113,8 +113,8 @@ public final class BedrockClientData { @Setter private String originalString = null; - public DeviceOs getDeviceOs() { - return deviceOs != null ? deviceOs : DeviceOs.UNKNOWN; + public BedrockPlatform getDeviceOs() { + return deviceOs != null ? deviceOs : BedrockPlatform.UNKNOWN; } public InputMode getCurrentInputMode() { diff --git a/core/src/main/java/org/geysermc/geyser/skin/FloodgateSkinUploader.java b/core/src/main/java/org/geysermc/geyser/skin/BedrockSkinUploader.java similarity index 92% rename from core/src/main/java/org/geysermc/geyser/skin/FloodgateSkinUploader.java rename to core/src/main/java/org/geysermc/geyser/skin/BedrockSkinUploader.java index 6655c1a92..5b98c004a 100644 --- a/core/src/main/java/org/geysermc/geyser/skin/FloodgateSkinUploader.java +++ b/core/src/main/java/org/geysermc/geyser/skin/BedrockSkinUploader.java @@ -32,26 +32,23 @@ import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.nimbusds.jwt.SignedJWT; import lombok.Getter; -import org.geysermc.floodgate.pluginmessage.PluginMessageChannels; import org.geysermc.floodgate.util.WebsocketEventType; import org.geysermc.geyser.Constants; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserLogger; import org.geysermc.geyser.session.GeyserSession; -import org.geysermc.geyser.util.PluginMessageUtils; import org.java_websocket.client.WebSocketClient; import org.java_websocket.handshake.ServerHandshake; import javax.net.ssl.SSLException; import java.net.ConnectException; -import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; -public final class FloodgateSkinUploader { +public final class BedrockSkinUploader { private final ObjectMapper JACKSON = new ObjectMapper(); private final List skinQueue = new ArrayList<>(); @@ -61,9 +58,8 @@ public final class FloodgateSkinUploader { @Getter private int id; @Getter private String verifyCode; - @Getter private int subscribersCount; - public FloodgateSkinUploader(GeyserImpl geyser) { + public BedrockSkinUploader(GeyserImpl geyser) { this.logger = geyser.getLogger(); this.client = new WebSocketClient(Constants.GLOBAL_API_WS_URI) { @Override @@ -102,14 +98,11 @@ public final class FloodgateSkinUploader { verifyCode = node.get("verify_code").asText(); break; case SUBSCRIBER_COUNT: - subscribersCount = node.get("subscribers_count").asInt(); + logger.debug("Ignoring subscribers count message."); break; case SKIN_UPLOADED: // if Geyser is the only subscriber we have send it to the server manually // otherwise it's handled by the Floodgate plugin subscribers - if (subscribersCount != 1) { - break; - } String xuid = node.get("xuid").asText(); GeyserSession session = geyser.connectionByXuid(xuid); @@ -125,9 +118,7 @@ public final class FloodgateSkinUploader { String value = data.get("value").asText(); String signature = data.get("signature").asText(); - byte[] bytes = (value + '\0' + signature) - .getBytes(StandardCharsets.UTF_8); - PluginMessageUtils.sendMessage(session, PluginMessageChannels.SKIN, bytes); + geyser.getHybridProvider().onSkinUpload(session, value, signature); } break; case LOG_MESSAGE: @@ -226,7 +217,7 @@ public final class FloodgateSkinUploader { .schedule(client::reconnect, 8 + additionalTime, TimeUnit.SECONDS); } - public FloodgateSkinUploader start() { + public BedrockSkinUploader start() { client.connect(); return this; } diff --git a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/PistonBlockEntity.java b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/PistonBlockEntity.java index 40444ab72..3425b37d2 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/PistonBlockEntity.java +++ b/core/src/main/java/org/geysermc/geyser/translator/level/block/entity/PistonBlockEntity.java @@ -36,7 +36,6 @@ import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import lombok.Getter; -import org.geysermc.common.PlatformType; import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.level.physics.Axis; import org.geysermc.geyser.level.physics.BoundingBox; @@ -50,6 +49,7 @@ import org.geysermc.geyser.translator.collision.BlockCollision; import org.geysermc.geyser.util.BlockEntityUtils; import org.geysermc.geyser.util.BlockUtils; import org.geysermc.geyser.util.ChunkUtils; +import org.geysermc.geyser.util.PlatformType; import java.util.LinkedList; import java.util.Map; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockCommandRequestTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockCommandRequestTranslator.java index bc04bf50e..a2e09018d 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockCommandRequestTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockCommandRequestTranslator.java @@ -26,13 +26,13 @@ package org.geysermc.geyser.translator.protocol.bedrock; import org.cloudburstmc.protocol.bedrock.packet.CommandRequestPacket; -import org.geysermc.common.PlatformType; import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.ChatColor; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.translator.text.MessageTranslator; +import org.geysermc.geyser.util.PlatformType; @Translator(packet = CommandRequestPacket.class) public class BedrockCommandRequestTranslator extends PacketTranslator { diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockNetworkStackLatencyTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockNetworkStackLatencyTranslator.java index 7e5643d45..258c8c3d6 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockNetworkStackLatencyTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/bedrock/BedrockNetworkStackLatencyTranslator.java @@ -29,7 +29,7 @@ import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundKe import org.cloudburstmc.protocol.bedrock.data.AttributeData; import org.cloudburstmc.protocol.bedrock.packet.NetworkStackLatencyPacket; import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket; -import org.geysermc.floodgate.util.DeviceOs; +import org.geysermc.api.util.BedrockPlatform; import org.geysermc.geyser.entity.attribute.GeyserAttributeType; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; @@ -50,7 +50,7 @@ public class BedrockNetworkStackLatencyTranslator extends PacketTranslator { private final GeyserLogger logger = GeyserImpl.getInstance().getLogger(); @@ -56,89 +40,89 @@ public class JavaCustomPayloadTranslator extends PacketTranslator erosionPacket = Packets.decode(buf); - ((GeyserboundPacket) erosionPacket).handle(session.getErosionHandler()); - return; - } - - if (channel.equals(PluginMessageChannels.FORM)) { - session.ensureInEventLoop(() -> { - byte[] data = packet.getData(); - - // receive: first byte is form type, second and third are the id, remaining is the form data - // respond: first and second byte id, remaining is form response data - - FormType type = FormType.fromOrdinal(data[0]); - if (type == null) { - throw new NullPointerException("Got type " + data[0] + " which isn't a valid form type!"); - } - - String dataString = new String(data, 3, data.length - 3, Charsets.UTF_8); - - Form form = Forms.fromJson(dataString, type, (ignored, response) -> { - byte[] finalData; - if (response == null) { - // Response data can be null as of 1.19.20 (same behaviour as empty response data) - // Only need to send the form id - finalData = new byte[]{data[1], data[2]}; - } else { - byte[] raw = response.getBytes(StandardCharsets.UTF_8); - finalData = new byte[raw.length + 2]; - - finalData[0] = data[1]; - finalData[1] = data[2]; - System.arraycopy(raw, 0, finalData, 2, raw.length); - } - - session.sendDownstreamPacket(new ServerboundCustomPayloadPacket(channel, finalData)); - }); - session.sendForm(form); - }); - - } else if (channel.equals(PluginMessageChannels.TRANSFER)) { - session.ensureInEventLoop(() -> { - byte[] data = packet.getData(); - - // port (4 bytes), address (remaining data) - if (data.length < 5) { - throw new NullPointerException("Transfer data should be at least 5 bytes long"); - } - - int port = data[0] << 24 | (data[1] & 0xFF) << 16 | (data[2] & 0xFF) << 8 | data[3] & 0xFF; - String address = new String(data, 4, data.length - 4); - - if (logger.isDebug()) { - logger.info("Transferring client to: " + address + ":" + port); - } - - TransferPacket transferPacket = new TransferPacket(); - transferPacket.setAddress(address); - transferPacket.setPort(port); - session.sendUpstreamPacket(transferPacket); - }); - - } else if (channel.equals(PluginMessageChannels.PACKET)) { - session.ensureInEventLoop(() -> { - logger.debug("A packet has been sent using the Floodgate api"); - byte[] data = packet.getData(); - - // packet id, packet data - if (data.length < 2) { - throw new IllegalStateException("Packet data should be at least 2 bytes long"); - } - - int packetId = data[0] & 0xFF; - ByteBuf packetData = Unpooled.wrappedBuffer(data, 1, data.length - 1); - - var toSend = new UnknownPacket(); - toSend.setPacketId(packetId); - toSend.setPayload(packetData); - - session.sendUpstreamPacket(toSend); - }); - } +// if (channel.equals(Constants.PLUGIN_MESSAGE)) { +// ByteBuf buf = Unpooled.wrappedBuffer(packet.getData()); +// ErosionPacket erosionPacket = Packets.decode(buf); +// ((GeyserboundPacket) erosionPacket).handle(session.getErosionHandler()); +// return; +// } +// +// if (channel.equals(PluginMessageChannels.FORM)) { +// session.ensureInEventLoop(() -> { +// byte[] data = packet.getData(); +// +// // receive: first byte is form type, second and third are the id, remaining is the form data +// // respond: first and second byte id, remaining is form response data +// +// FormType type = FormType.fromOrdinal(data[0]); +// if (type == null) { +// throw new NullPointerException("Got type " + data[0] + " which isn't a valid form type!"); +// } +// +// String dataString = new String(data, 3, data.length - 3, Charsets.UTF_8); +// +// Form form = Forms.fromJson(dataString, type, (ignored, response) -> { +// byte[] finalData; +// if (response == null) { +// // Response data can be null as of 1.19.20 (same behaviour as empty response data) +// // Only need to send the form id +// finalData = new byte[]{data[1], data[2]}; +// } else { +// byte[] raw = response.getBytes(StandardCharsets.UTF_8); +// finalData = new byte[raw.length + 2]; +// +// finalData[0] = data[1]; +// finalData[1] = data[2]; +// System.arraycopy(raw, 0, finalData, 2, raw.length); +// } +// +// session.sendDownstreamPacket(new ServerboundCustomPayloadPacket(channel, finalData)); +// }); +// session.sendForm(form); +// }); +// +// } else if (channel.equals(PluginMessageChannels.TRANSFER)) { +// session.ensureInEventLoop(() -> { +// byte[] data = packet.getData(); +// +// // port (4 bytes), address (remaining data) +// if (data.length < 5) { +// throw new NullPointerException("Transfer data should be at least 5 bytes long"); +// } +// +// int port = data[0] << 24 | (data[1] & 0xFF) << 16 | (data[2] & 0xFF) << 8 | data[3] & 0xFF; +// String address = new String(data, 4, data.length - 4); +// +// if (logger.isDebug()) { +// logger.info("Transferring client to: " + address + ":" + port); +// } +// +// TransferPacket transferPacket = new TransferPacket(); +// transferPacket.setAddress(address); +// transferPacket.setPort(port); +// session.sendUpstreamPacket(transferPacket); +// }); +// +// } else if (channel.equals(PluginMessageChannels.PACKET)) { +// session.ensureInEventLoop(() -> { +// logger.debug("A packet has been sent using the Floodgate api"); +// byte[] data = packet.getData(); +// +// // packet id, packet data +// if (data.length < 2) { +// throw new IllegalStateException("Packet data should be at least 2 bytes long"); +// } +// +// int packetId = data[0] & 0xFF; +// ByteBuf packetData = Unpooled.wrappedBuffer(data, 1, data.length - 1); +// +// var toSend = new UnknownPacket(); +// toSend.setPacketId(packetId); +// toSend.setPayload(packetData); +// +// session.sendUpstreamPacket(toSend); +// }); +// } } @Override diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginDisconnectTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginDisconnectTranslator.java index 0720963fb..1c5c2ade4 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginDisconnectTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginDisconnectTranslator.java @@ -29,13 +29,13 @@ import com.github.steveice10.mc.protocol.packet.login.clientbound.ClientboundLog import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.TranslatableComponent; -import org.geysermc.common.PlatformType; import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.translator.text.MessageTranslator; +import org.geysermc.geyser.util.PlatformType; import java.util.List; diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java index 3d9f08ec7..b7904183d 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaLoginTranslator.java @@ -33,7 +33,6 @@ import org.cloudburstmc.protocol.bedrock.data.GameRuleData; import org.cloudburstmc.protocol.bedrock.packet.GameRulesChangedPacket; import org.cloudburstmc.protocol.bedrock.packet.SetPlayerGameTypePacket; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import org.geysermc.floodgate.pluginmessage.PluginMessageChannels; import org.geysermc.geyser.api.network.AuthType; import org.geysermc.geyser.entity.type.player.SessionPlayerEntity; import org.geysermc.geyser.erosion.GeyserboundHandshakePacketHandler; @@ -141,7 +140,8 @@ public class JavaLoginTranslator extends PacketTranslator { diff --git a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockUpdateTranslator.java b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockUpdateTranslator.java index 6a8a2a5ba..49b3e8663 100644 --- a/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockUpdateTranslator.java +++ b/core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaBlockUpdateTranslator.java @@ -29,13 +29,13 @@ import com.github.steveice10.mc.protocol.packet.ingame.clientbound.level.Clientb import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.protocol.bedrock.data.SoundEvent; import org.cloudburstmc.protocol.bedrock.packet.LevelSoundEventPacket; -import org.geysermc.common.PlatformType; import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.type.BlockMapping; import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.translator.sound.BlockSoundInteractionTranslator; +import org.geysermc.geyser.util.PlatformType; @Translator(packet = ClientboundBlockUpdatePacket.class) public class JavaBlockUpdateTranslator extends PacketTranslator { diff --git a/common/src/main/java/org/geysermc/common/PlatformType.java b/core/src/main/java/org/geysermc/geyser/util/PlatformType.java similarity index 97% rename from common/src/main/java/org/geysermc/common/PlatformType.java rename to core/src/main/java/org/geysermc/geyser/util/PlatformType.java index 667d49a7a..8e2c927ad 100644 --- a/common/src/main/java/org/geysermc/common/PlatformType.java +++ b/core/src/main/java/org/geysermc/geyser/util/PlatformType.java @@ -23,7 +23,7 @@ * @link https://github.com/GeyserMC/Geyser */ -package org.geysermc.common; +package org.geysermc.geyser.util; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/core/src/main/resources/config.yml b/core/src/main/resources/config.yml index 421ad4c1c..136c22a9f 100644 --- a/core/src/main/resources/config.yml +++ b/core/src/main/resources/config.yml @@ -212,12 +212,6 @@ enable-proxy-connections: false # 1400 is the default. mtu: 1400 -# Whether to connect directly into the Java server without creating a TCP connection. -# This should only be disabled if a plugin that interfaces with packets or the network does not work correctly with Geyser. -# If enabled on plugin versions, the remote address and port sections are ignored -# If disabled on plugin versions, expect performance decrease and latency increase -use-direct-connection: true - # Whether Geyser should attempt to disable compression for Bedrock players. This should be a benefit as there is no need to compress data # when Java packets aren't being handled over the network. # This requires use-direct-connection to be true. diff --git a/gradle.properties b/gradle.properties index 4fb72e2fc..27a868f1c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,8 +5,6 @@ org.gradle.caching=true org.gradle.parallel=true group=org.geysermc -version=2.1.0-SNAPSHOT +version=3.0.0-SNAPSHOT -org.gradle.caching=true -org.gradle.parallel=true org.gradle.vfs.watch=false \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index e9c7641e4..9befda626 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -3,6 +3,7 @@ enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") dependencyResolutionManagement { // repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { + mavenLocal() // Floodgate, Cumulus etc. maven("https://repo.opencollab.dev/main") @@ -24,7 +25,6 @@ dependencyResolutionManagement { mavenContent { releasesOnly() } } - mavenLocal() mavenCentral() // ViaVersion