diff --git a/build.gradle b/build.gradle index bfa7224f..7dd52402 100644 --- a/build.gradle +++ b/build.gradle @@ -110,7 +110,6 @@ task remappedShadowJar(type: RemapJarTask) { dependsOn tasks.shadowJar input = tasks.shadowJar.archiveFile addNestedDependencies = true - //remapAccessWidener = true // Required for our access widener changes to go into effect and not crash on startup archiveName = "floodgate-fabric.jar" } diff --git a/src/main/java/org/geysermc/floodgate/FabricMod.java b/src/main/java/org/geysermc/floodgate/FabricMod.java index 91a51de0..558f8ff0 100644 --- a/src/main/java/org/geysermc/floodgate/FabricMod.java +++ b/src/main/java/org/geysermc/floodgate/FabricMod.java @@ -8,9 +8,6 @@ import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; import net.fabricmc.loader.api.FabricLoader; import org.geysermc.floodgate.api.logger.FloodgateLogger; import org.geysermc.floodgate.module.*; -import org.geysermc.floodgate.pluginmessage.FabricSkinApplier; -import org.geysermc.floodgate.util.FabricCommandUtil; -import org.geysermc.floodgate.util.FabricPlatformUtils; public class FabricMod implements ModInitializer { @Override @@ -31,9 +28,7 @@ public class FabricMod implements ModInitializer { // Stupid hack, see the class for more information // This can probably be Guice-i-fied but that is beyond me - FabricCommandUtil.setServer(server); - FabricSkinApplier.setServer(server); - FabricPlatformUtils.setServer(server); + MinecraftServerHolder.set(server); platform.enable( new FabricAddonModule(), diff --git a/src/main/java/org/geysermc/floodgate/MinecraftServerHolder.java b/src/main/java/org/geysermc/floodgate/MinecraftServerHolder.java new file mode 100644 index 00000000..b1f0c9e6 --- /dev/null +++ b/src/main/java/org/geysermc/floodgate/MinecraftServerHolder.java @@ -0,0 +1,20 @@ +package org.geysermc.floodgate; + +import net.minecraft.server.MinecraftServer; + +public final class MinecraftServerHolder { + // Static because commands *need* to be initialized before the server is available + // Otherwise it would be a class variable + private static MinecraftServer INSTANCE; + + public static MinecraftServer get() { + return INSTANCE; + } + + static void set(MinecraftServer instance) { + INSTANCE = instance; + } + + private MinecraftServerHolder() { + } +} diff --git a/src/main/java/org/geysermc/floodgate/addon/data/FabricDataHandler.java b/src/main/java/org/geysermc/floodgate/addon/data/FabricDataHandler.java index 71a5aa2e..32a646a0 100644 --- a/src/main/java/org/geysermc/floodgate/addon/data/FabricDataHandler.java +++ b/src/main/java/org/geysermc/floodgate/addon/data/FabricDataHandler.java @@ -1,12 +1,15 @@ package org.geysermc.floodgate.addon.data; +import com.mojang.logging.LogUtils; import io.netty.channel.Channel; import io.netty.util.AttributeKey; +import net.minecraft.DefaultUncaughtExceptionHandler; import net.minecraft.network.Connection; import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.handshake.ClientIntentionPacket; import net.minecraft.network.protocol.login.ServerboundHelloPacket; import net.minecraft.server.network.ServerLoginPacketListenerImpl; +import org.geysermc.floodgate.MinecraftServerHolder; import org.geysermc.floodgate.api.logger.FloodgateLogger; import org.geysermc.floodgate.mixin.ConnectionMixin; import org.geysermc.floodgate.mixin.ClientIntentionPacketMixin; @@ -17,10 +20,13 @@ import org.geysermc.floodgate.api.player.FloodgatePlayer; import org.geysermc.floodgate.config.FloodgateConfig; import org.geysermc.floodgate.player.FloodgateHandshakeHandler; import org.geysermc.floodgate.player.FloodgateHandshakeHandler.HandshakeResult; +import org.slf4j.Logger; import java.net.InetSocketAddress; public final class FabricDataHandler extends CommonDataHandler { + private static final Logger LOGGER = LogUtils.getLogger(); + private final FloodgateLogger logger; private Connection networkManager; private FloodgatePlayer player; @@ -95,8 +101,27 @@ public final class FabricDataHandler extends CommonDataHandler { GameProfile gameProfile = new GameProfile(player.getCorrectUniqueId(), player.getCorrectUsername()); - ((ServerLoginPacketListenerSetter) networkManager.getPacketListener()).setGameProfile(gameProfile); - ((ServerLoginPacketListenerSetter) networkManager.getPacketListener()).setLoginState(); + if (player.isLinked() && player.getCorrectUniqueId().version() == 4) { + Thread texturesThread = new Thread("Bedrock Linked Player Texture Download") { + @Override + public void run() { + try { + MinecraftServerHolder.get().getSessionService() + .fillProfileProperties(gameProfile, true); + } catch (Exception e) { + LOGGER.error("Unable to get Bedrock linked player textures for " + gameProfile.getName(), e); + } + ((ServerLoginPacketListenerSetter) networkManager.getPacketListener()) + .setGameProfile(gameProfile); + ((ServerLoginPacketListenerSetter) networkManager.getPacketListener()).setLoginState(); + } + }; + texturesThread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(LOGGER)); + texturesThread.start(); + } else { + ((ServerLoginPacketListenerSetter) networkManager.getPacketListener()).setGameProfile(gameProfile); + ((ServerLoginPacketListenerSetter) networkManager.getPacketListener()).setLoginState(); + } ctx.pipeline().remove(this); return true; diff --git a/src/main/java/org/geysermc/floodgate/module/FabricPlatformModule.java b/src/main/java/org/geysermc/floodgate/module/FabricPlatformModule.java index 3cc792d7..56ada8dd 100644 --- a/src/main/java/org/geysermc/floodgate/module/FabricPlatformModule.java +++ b/src/main/java/org/geysermc/floodgate/module/FabricPlatformModule.java @@ -6,7 +6,9 @@ import org.geysermc.floodgate.listener.FabricEventRegistration; import org.geysermc.floodgate.logger.Log4jFloodgateLogger; import org.geysermc.floodgate.platform.listener.ListenerRegistration; import org.geysermc.floodgate.platform.util.PlatformUtils; +import org.geysermc.floodgate.pluginmessage.FabricPluginMessageRegistration; import org.geysermc.floodgate.pluginmessage.FabricSkinApplier; +import org.geysermc.floodgate.pluginmessage.PluginMessageRegistration; import org.geysermc.floodgate.util.FabricCommandUtil; import com.google.inject.AbstractModule; import com.google.inject.Provides; @@ -85,6 +87,12 @@ public final class FabricPlatformModule extends AbstractModule { return "Fabric"; } + @Provides + @Singleton + public PluginMessageRegistration pluginMessageRegister() { + return new FabricPluginMessageRegistration(); + } + @Provides @Singleton public SkinApplier skinApplier() { diff --git a/src/main/java/org/geysermc/floodgate/pluginmessage/FabricPluginMessageRegistration.java b/src/main/java/org/geysermc/floodgate/pluginmessage/FabricPluginMessageRegistration.java new file mode 100644 index 00000000..1d0e4be2 --- /dev/null +++ b/src/main/java/org/geysermc/floodgate/pluginmessage/FabricPluginMessageRegistration.java @@ -0,0 +1,17 @@ +package org.geysermc.floodgate.pluginmessage; + +import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; +import net.minecraft.resources.ResourceLocation; + +public class FabricPluginMessageRegistration implements PluginMessageRegistration { + @Override + public void register(PluginMessageChannel channel) { + ServerPlayNetworking.registerGlobalReceiver(new ResourceLocation(channel.getIdentifier()), + (server, player, handler, buf, responseSender) -> { + System.out.println("Received channel of " + channel.getIdentifier()); + byte[] bytes = new byte[buf.readableBytes()]; + buf.readBytes(bytes); + channel.handleServerCall(bytes, player.getUUID(), player.getGameProfile().getName()); + }); + } +} diff --git a/src/main/java/org/geysermc/floodgate/pluginmessage/FabricSkinApplier.java b/src/main/java/org/geysermc/floodgate/pluginmessage/FabricSkinApplier.java index c0fa023a..788102df 100644 --- a/src/main/java/org/geysermc/floodgate/pluginmessage/FabricSkinApplier.java +++ b/src/main/java/org/geysermc/floodgate/pluginmessage/FabricSkinApplier.java @@ -3,23 +3,23 @@ package org.geysermc.floodgate.pluginmessage; import com.mojang.authlib.properties.Property; import com.mojang.authlib.properties.PropertyMap; import net.minecraft.network.protocol.game.ClientboundPlayerInfoPacket; -import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ChunkMap; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; +import org.geysermc.floodgate.MinecraftServerHolder; import org.geysermc.floodgate.api.player.FloodgatePlayer; import org.geysermc.floodgate.mixin.ChunkMapMixin; import org.geysermc.floodgate.skin.SkinApplier; import org.geysermc.floodgate.skin.SkinData; public final class FabricSkinApplier implements SkinApplier { - // See FabricCommandUtil - private static MinecraftServer SERVER; @Override public void applySkin(FloodgatePlayer floodgatePlayer, SkinData skinData) { - SERVER.execute(() -> { - ServerPlayer bedrockPlayer = SERVER.getPlayerList().getPlayer(floodgatePlayer.getCorrectUniqueId()); + MinecraftServerHolder.get().execute(() -> { + System.out.println("Refreshing skins for " + floodgatePlayer); + ServerPlayer bedrockPlayer = MinecraftServerHolder.get().getPlayerList() + .getPlayer(floodgatePlayer.getCorrectUniqueId()); if (bedrockPlayer == null) { // Disconnected probably? return; @@ -33,24 +33,28 @@ public final class FabricSkinApplier implements SkinApplier { ChunkMap tracker = ((ServerLevel) bedrockPlayer.level).getChunkSource().chunkMap; ChunkMap.TrackedEntity entry = ((ChunkMapMixin) tracker).getEntityMap().get(bedrockPlayer.getId()); - entry.broadcastRemoved(); + + System.out.println("eeeee"); // Skin is applied - now it's time to refresh the player for everyone. - for (ServerPlayer otherPlayer : SERVER.getPlayerList().getPlayers()) { - if (otherPlayer == bedrockPlayer) { - continue; + for (ServerPlayer otherPlayer : MinecraftServerHolder.get().getPlayerList().getPlayers()) { + boolean samePlayer = otherPlayer == bedrockPlayer; + if (!samePlayer) { + // TrackedEntity#broadcastRemoved doesn't actually remove them from seenBy + entry.removePlayer(otherPlayer); } otherPlayer.connection.send(new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.REMOVE_PLAYER, bedrockPlayer)); otherPlayer.connection.send(new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.ADD_PLAYER, bedrockPlayer)); + if (samePlayer) { + continue; + } + if (bedrockPlayer.level == otherPlayer.level) { + System.out.println("Updating entry"); entry.updatePlayer(otherPlayer); } } }); } - - public static void setServer(MinecraftServer server) { - SERVER = server; - } } diff --git a/src/main/java/org/geysermc/floodgate/util/FabricCommandUtil.java b/src/main/java/org/geysermc/floodgate/util/FabricCommandUtil.java index a976bca6..15086a70 100644 --- a/src/main/java/org/geysermc/floodgate/util/FabricCommandUtil.java +++ b/src/main/java/org/geysermc/floodgate/util/FabricCommandUtil.java @@ -4,11 +4,11 @@ import com.mojang.authlib.GameProfile; import me.lucko.fabric.api.permissions.v0.Permissions; import net.minecraft.commands.CommandSourceStack; import net.minecraft.network.chat.Component; -import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.players.UserWhiteListEntry; import net.minecraft.world.entity.Entity; import org.checkerframework.checker.nullness.qual.NonNull; +import org.geysermc.floodgate.MinecraftServerHolder; import org.geysermc.floodgate.api.FloodgateApi; import org.geysermc.floodgate.api.logger.FloodgateLogger; import org.geysermc.floodgate.platform.command.CommandUtil; @@ -17,10 +17,6 @@ import org.geysermc.floodgate.player.UserAudience; import java.util.*; public final class FabricCommandUtil extends CommandUtil { - // Static because commands *need* to be initialized before the server is available - // Otherwise it would be a class variable - private static MinecraftServer SERVER; - private final FloodgateLogger logger; private UserAudience console; @@ -58,19 +54,19 @@ public final class FabricCommandUtil extends CommandUtil { @Override public Object getPlayerByUuid(@NonNull UUID uuid) { - ServerPlayer player = SERVER.getPlayerList().getPlayer(uuid); + ServerPlayer player = MinecraftServerHolder.get().getPlayerList().getPlayer(uuid); return player != null ? player : uuid; } @Override public Object getPlayerByUsername(@NonNull String username) { - ServerPlayer player = SERVER.getPlayerList().getPlayerByName(username); + ServerPlayer player = MinecraftServerHolder.get().getPlayerList().getPlayerByName(username); return player != null ? player : username; } @Override protected Collection getOnlinePlayers() { - return SERVER.getPlayerList().getPlayers(); + return MinecraftServerHolder.get().getPlayerList().getPlayers(); } @Override @@ -82,7 +78,7 @@ public final class FabricCommandUtil extends CommandUtil { public void sendMessage(Object target, String message) { CommandSourceStack commandSource = (CommandSourceStack) target; if (commandSource.getEntity() instanceof ServerPlayer) { - SERVER.execute(() -> ((ServerPlayer) commandSource.getEntity()) + MinecraftServerHolder.get().execute(() -> ((ServerPlayer) commandSource.getEntity()) .displayClientMessage(Component.literal(message), false)); } else { // Console? @@ -100,18 +96,14 @@ public final class FabricCommandUtil extends CommandUtil { @Override public boolean whitelistPlayer(UUID uuid, String username) { GameProfile profile = new GameProfile(uuid, username); - SERVER.getPlayerList().getWhiteList().add(new UserWhiteListEntry(profile)); + MinecraftServerHolder.get().getPlayerList().getWhiteList().add(new UserWhiteListEntry(profile)); return true; } @Override public boolean removePlayerFromWhitelist(UUID uuid, String username) { GameProfile profile = new GameProfile(uuid, username); - SERVER.getPlayerList().getWhiteList().remove(profile); + MinecraftServerHolder.get().getPlayerList().getWhiteList().remove(profile); return true; } - - public static void setServer(MinecraftServer server) { - SERVER = server; - } } diff --git a/src/main/java/org/geysermc/floodgate/util/FabricPlatformUtils.java b/src/main/java/org/geysermc/floodgate/util/FabricPlatformUtils.java index a355fe1f..900ec2dc 100644 --- a/src/main/java/org/geysermc/floodgate/util/FabricPlatformUtils.java +++ b/src/main/java/org/geysermc/floodgate/util/FabricPlatformUtils.java @@ -1,15 +1,13 @@ package org.geysermc.floodgate.util; import net.minecraft.SharedConstants; -import net.minecraft.server.MinecraftServer; +import org.geysermc.floodgate.MinecraftServerHolder; import org.geysermc.floodgate.platform.util.PlatformUtils; public class FabricPlatformUtils extends PlatformUtils { - private static MinecraftServer SERVER; - @Override public AuthType authType() { - return SERVER.usesAuthentication() ? AuthType.ONLINE : AuthType.OFFLINE; + return MinecraftServerHolder.get().usesAuthentication() ? AuthType.ONLINE : AuthType.OFFLINE; } @Override @@ -19,10 +17,6 @@ public class FabricPlatformUtils extends PlatformUtils { @Override public String serverImplementationName() { - return "Fabric"; - } - - public static void setServer(MinecraftServer server) { - SERVER = server; + return MinecraftServerHolder.get().getServerModName(); } }