diff --git a/build.gradle b/build.gradle index 610d1979..bfa7224f 100644 --- a/build.gradle +++ b/build.gradle @@ -2,7 +2,7 @@ import net.fabricmc.loom.task.RemapJarTask plugins { id 'com.github.johnrengelman.shadow' version '7.0.0' - id 'fabric-loom' version '0.10-SNAPSHOT' + id 'fabric-loom' version '0.12-SNAPSHOT' id 'java' id 'maven-publish' } @@ -14,8 +14,8 @@ archivesBaseName = project.archives_base_name version = project.mod_version group = project.maven_group -minecraft { - accessWidener = file("src/main/resources/floodgate.accesswidener") +loom { + accessWidenerPath = file("src/main/resources/floodgate.accesswidener") } dependencies { @@ -31,19 +31,20 @@ dependencies { // You may need to force-disable transitiveness on them. // Base Floodgate - implementation("org.geysermc.floodgate:common:${project.mod_version}") - shadow("org.geysermc.floodgate:common:${project.mod_version}") { + implementation("org.geysermc.floodgate:core:${project.mod_version}") + shadow("org.geysermc.floodgate:core:${project.mod_version}") { exclude group: 'com.google.guava', module: "guava" exclude group: 'com.google.code.gson', module: "gson" exclude group: 'org.slf4j', module: "slf4j-api" exclude group: 'net.kyori', module: '*' // Let Adventure-Platform provide its desired Adventure version + exclude group: 'it.unimi.dsi.fastutil', module: "*" } - include(modImplementation('cloud.commandframework:cloud-fabric:1.5.0') { + include(modImplementation('cloud.commandframework:cloud-fabric:1.7.0-SNAPSHOT') { because "Commands library implementation for Fabric" }) - include(modImplementation('net.kyori:adventure-platform-fabric:5.2.1') { + include(modImplementation('net.kyori:adventure-platform-fabric:5.4.0-SNAPSHOT') { because "Chat library implementation for Fabric that includes methods for communicating with the server" // Thanks to zml for this fix // The package modifies Brigadier which causes a LinkageError at runtime if included @@ -60,6 +61,12 @@ repositories { maven { url = 'https://oss.sonatype.org/content/repositories/snapshots' } + // specifically for adventure-platform-fabric:5.4.0-SNAPSHOT + maven { + name = "sonatype-oss-snapshots1" + url = "https://s01.oss.sonatype.org/content/repositories/snapshots/" + mavenContent { snapshotsOnly() } + } // Standard OpenCollab repositories maven { name = 'opencollab-release-repo' @@ -96,29 +103,14 @@ task sourcesJar(type: Jar, dependsOn: classes) { } shadowJar { -// dependencies { -// exclude('net.fabricmc:.*') -// //include(dependency('org.geysermc.floodgate:.*')) -// //include(dependency("org.geysermc.cumulus:.*")) -// //include(dependency('org.geysermc:.*')) -// exclude '/mappings/*' -// } configurations = [project.configurations.shadow] - //dependencies { - //exclude(dependency('cloud.commandframework:cloud-fabric:.*')) - //exclude(dependency('net.kyori:adventure-platform-fabric:.*')) - //} - - //relocate 'net.kyori', 'org.geysermc.floodgate.relocations.kyori' - //relocate 'cloud.commandframework', 'org.geysermc.floodgate.relocations.cloud' - relocate 'it.unimi.dsi.fastutil', 'org.geysermc.floodgate.relocations.fastutil' } task remappedShadowJar(type: RemapJarTask) { dependsOn tasks.shadowJar - input = tasks.shadowJar.archivePath + input = tasks.shadowJar.archiveFile addNestedDependencies = true - remapAccessWidener = true // Required for our access widener changes to go into effect and not crash on startup + //remapAccessWidener = true // Required for our access widener changes to go into effect and not crash on startup archiveName = "floodgate-fabric.jar" } diff --git a/gradle.properties b/gradle.properties index 4d8c440b..0c43ff6a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,15 +1,15 @@ # Done to increase the memory available to gradle. -org.gradle.jvmargs=-Xmx1G +org.gradle.jvmargs=-Xmx2G # Fabric Properties # check these on https://modmuss50.me/fabric.html -minecraft_version=1.18.2 -loader_version=0.12.6 +minecraft_version=1.19 +loader_version=0.14.6 # Mod Properties -mod_version=2.1.0-SNAPSHOT +mod_version=2.2.0-SNAPSHOT maven_group=org.geysermc.floodgate archives_base_name=floodgate-fabric # Dependencies # check this on https://modmuss50.me/fabric.html -fabric_version=0.43.1+1.18 +fabric_version=0.55.3+1.19 # Our stuff lombok_version=1.18.20 diff --git a/src/main/java/org/geysermc/floodgate/FabricMod.java b/src/main/java/org/geysermc/floodgate/FabricMod.java index 6b2a3bd0..91a51de0 100644 --- a/src/main/java/org/geysermc/floodgate/FabricMod.java +++ b/src/main/java/org/geysermc/floodgate/FabricMod.java @@ -6,11 +6,11 @@ import com.google.inject.Injector; import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; import net.fabricmc.loader.api.FabricLoader; -import net.kyori.adventure.platform.fabric.FabricServerAudiences; 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 @@ -29,12 +29,11 @@ public class FabricMod implements ModInitializer { ServerLifecycleEvents.SERVER_STARTED.register((server) -> { long ctm = System.currentTimeMillis(); - FabricServerAudiences adventure = FabricServerAudiences.of(server); - // Stupid hack, see the class for more information // This can probably be Guice-i-fied but that is beyond me - FabricCommandUtil.setLaterVariables(server, adventure); + FabricCommandUtil.setServer(server); FabricSkinApplier.setServer(server); + FabricPlatformUtils.setServer(server); platform.enable( new FabricAddonModule(), diff --git a/src/main/java/org/geysermc/floodgate/addon/data/FabricDataAddon.java b/src/main/java/org/geysermc/floodgate/addon/data/FabricDataAddon.java index 6cab89d5..ca93aae4 100644 --- a/src/main/java/org/geysermc/floodgate/addon/data/FabricDataAddon.java +++ b/src/main/java/org/geysermc/floodgate/addon/data/FabricDataAddon.java @@ -41,7 +41,7 @@ public final class FabricDataAddon implements InjectorAddon { @Override public void onChannelClosed(Channel channel) { FloodgatePlayer player = channel.attr(playerAttribute).get(); - if (player != null && api.removePlayer(player)) { + if (player != null && api.setPendingRemove(player)) { logger.translatedInfo("floodgate.ingame.disconnect_name", player.getCorrectUsername()); } } diff --git a/src/main/java/org/geysermc/floodgate/listener/FabricEventListener.java b/src/main/java/org/geysermc/floodgate/listener/FabricEventListener.java index bb5cbe12..b94e1d30 100644 --- a/src/main/java/org/geysermc/floodgate/listener/FabricEventListener.java +++ b/src/main/java/org/geysermc/floodgate/listener/FabricEventListener.java @@ -7,7 +7,6 @@ import net.minecraft.server.network.ServerGamePacketListenerImpl; import org.geysermc.floodgate.api.FloodgateApi; import org.geysermc.floodgate.api.logger.FloodgateLogger; import org.geysermc.floodgate.api.player.FloodgatePlayer; -import org.geysermc.floodgate.player.FloodgatePlayerImpl; import org.geysermc.floodgate.util.LanguageManager; public final class FabricEventListener { @@ -18,7 +17,6 @@ public final class FabricEventListener { public void onPlayerJoin(ServerGamePacketListenerImpl networkHandler, PacketSender packetSender, MinecraftServer server) { FloodgatePlayer player = api.getPlayer(networkHandler.player.getUUID()); if (player != null) { - player.as(FloodgatePlayerImpl.class).setLogin(false); logger.translatedInfo( "floodgate.ingame.login_name", player.getCorrectUsername(), player.getCorrectUniqueId() diff --git a/src/main/java/org/geysermc/floodgate/mixin/ChunkMapMixin.java b/src/main/java/org/geysermc/floodgate/mixin/ChunkMapMixin.java new file mode 100644 index 00000000..3805dbb5 --- /dev/null +++ b/src/main/java/org/geysermc/floodgate/mixin/ChunkMapMixin.java @@ -0,0 +1,12 @@ +package org.geysermc.floodgate.mixin; + +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import net.minecraft.server.level.ChunkMap; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(ChunkMap.class) +public interface ChunkMapMixin { + @Accessor("entityMap") + Int2ObjectMap getEntityMap(); +} diff --git a/src/main/java/org/geysermc/floodgate/module/FabricCommandModule.java b/src/main/java/org/geysermc/floodgate/module/FabricCommandModule.java index 3d824010..c6730278 100644 --- a/src/main/java/org/geysermc/floodgate/module/FabricCommandModule.java +++ b/src/main/java/org/geysermc/floodgate/module/FabricCommandModule.java @@ -19,7 +19,7 @@ public final class FabricCommandModule extends CommandModule { public CommandManager commandManager(CommandUtil commandUtil) { FabricCommandManager commandManager = new FabricServerCommandManager<>( CommandExecutionCoordinator.simpleCoordinator(), - commandUtil::getAudience, + commandUtil::getUserAudience, audience -> (CommandSourceStack) audience.source() ); commandManager.registerCommandPreProcessor(new FloodgateCommandPreprocessor<>(commandUtil)); diff --git a/src/main/java/org/geysermc/floodgate/module/FabricPlatformModule.java b/src/main/java/org/geysermc/floodgate/module/FabricPlatformModule.java index 87a7eea3..3cc792d7 100644 --- a/src/main/java/org/geysermc/floodgate/module/FabricPlatformModule.java +++ b/src/main/java/org/geysermc/floodgate/module/FabricPlatformModule.java @@ -5,6 +5,7 @@ import org.geysermc.floodgate.listener.FabricEventListener; 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.FabricSkinApplier; import org.geysermc.floodgate.util.FabricCommandUtil; import com.google.inject.AbstractModule; @@ -18,11 +19,17 @@ import org.geysermc.floodgate.api.logger.FloodgateLogger; import org.geysermc.floodgate.inject.CommonPlatformInjector; import org.geysermc.floodgate.platform.command.CommandUtil; import org.geysermc.floodgate.skin.SkinApplier; +import org.geysermc.floodgate.util.FabricPlatformUtils; import org.geysermc.floodgate.util.LanguageManager; @RequiredArgsConstructor public final class FabricPlatformModule extends AbstractModule { + @Override + protected void configure() { + bind(PlatformUtils.class).to(FabricPlatformUtils.class); + } + @Provides @Singleton public FloodgateLogger floodgateLogger(LanguageManager languageManager) { @@ -35,7 +42,7 @@ public final class FabricPlatformModule extends AbstractModule { FloodgateApi api, FloodgateLogger logger, LanguageManager languageManager) { - return new FabricCommandUtil(api, logger, languageManager); + return new FabricCommandUtil(languageManager, api, logger); } @Provides diff --git a/src/main/java/org/geysermc/floodgate/pluginmessage/FabricSkinApplier.java b/src/main/java/org/geysermc/floodgate/pluginmessage/FabricSkinApplier.java index b38be056..c0fa023a 100644 --- a/src/main/java/org/geysermc/floodgate/pluginmessage/FabricSkinApplier.java +++ b/src/main/java/org/geysermc/floodgate/pluginmessage/FabricSkinApplier.java @@ -1,26 +1,17 @@ package org.geysermc.floodgate.pluginmessage; -import com.google.common.collect.Lists; import com.mojang.authlib.properties.Property; import com.mojang.authlib.properties.PropertyMap; -import com.mojang.datafixers.util.Pair; -import lombok.RequiredArgsConstructor; -import net.minecraft.network.protocol.Packet; -import net.minecraft.network.protocol.game.*; +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 net.minecraft.world.effect.MobEffectInstance; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.ai.attributes.AttributeInstance; -import net.minecraft.world.item.ItemStack; 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; -import java.util.Collection; -import java.util.List; - -@RequiredArgsConstructor public final class FabricSkinApplier implements SkinApplier { // See FabricCommandUtil private static MinecraftServer SERVER; @@ -40,60 +31,20 @@ public final class FabricSkinApplier implements SkinApplier { properties.removeAll("textures"); properties.put("textures", new Property("textures", skinData.getValue(), skinData.getSignature())); - // Skin is applied - now it's time to refresh the player for everyone. Oof. + ChunkMap tracker = ((ServerLevel) bedrockPlayer.level).getChunkSource().chunkMap; + ChunkMap.TrackedEntity entry = ((ChunkMapMixin) tracker).getEntityMap().get(bedrockPlayer.getId()); + entry.broadcastRemoved(); + + // Skin is applied - now it's time to refresh the player for everyone. for (ServerPlayer otherPlayer : SERVER.getPlayerList().getPlayers()) { if (otherPlayer == bedrockPlayer) { continue; } - boolean loadedInWorld = otherPlayer.getCommandSenderWorld().getEntity(bedrockPlayer.getId()) != null; - if (loadedInWorld) { - // Player is loaded in this world - otherPlayer.connection.send(new ClientboundRemoveEntitiesPacket(bedrockPlayer.getId())); - } otherPlayer.connection.send(new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.REMOVE_PLAYER, bedrockPlayer)); - otherPlayer.connection.send(new ClientboundPlayerInfoPacket(ClientboundPlayerInfoPacket.Action.ADD_PLAYER, bedrockPlayer)); - if (loadedInWorld) { - // Copied from EntityTrackerEntry - Packet spawnPacket = bedrockPlayer.getAddEntityPacket(); - otherPlayer.connection.send(spawnPacket); - if (!bedrockPlayer.getEntityData().isEmpty()) { - otherPlayer.connection.send(new ClientboundSetEntityDataPacket(bedrockPlayer.getId(), bedrockPlayer.getEntityData(), true)); - } - - Collection collection = bedrockPlayer.getAttributes().getDirtyAttributes(); - if (!collection.isEmpty()) { - otherPlayer.connection.send(new ClientboundUpdateAttributesPacket(bedrockPlayer.getId(), collection)); - } - - otherPlayer.connection.send(new ClientboundSetEntityMotionPacket(bedrockPlayer.getId(), bedrockPlayer.getDeltaMovement())); - - List> equipmentList = Lists.newArrayList(); - EquipmentSlot[] slots = EquipmentSlot.values(); - - for (EquipmentSlot equipmentSlot : slots) { - ItemStack itemStack = bedrockPlayer.getItemBySlot(equipmentSlot); - if (!itemStack.isEmpty()) { - equipmentList.add(Pair.of(equipmentSlot, itemStack.copy())); - } - } - - if (!equipmentList.isEmpty()) { - otherPlayer.connection.send(new ClientboundSetEquipmentPacket(bedrockPlayer.getId(), equipmentList)); - } - - for (MobEffectInstance mobEffectInstance : bedrockPlayer.getActiveEffects()) { - otherPlayer.connection.send(new ClientboundUpdateMobEffectPacket(bedrockPlayer.getId(), mobEffectInstance)); - } - - if (!bedrockPlayer.getPassengers().isEmpty()) { - otherPlayer.connection.send(new ClientboundSetPassengersPacket(bedrockPlayer)); - } - - if (bedrockPlayer.getVehicle() != null) { - otherPlayer.connection.send(new ClientboundSetPassengersPacket(bedrockPlayer.getVehicle())); - } + if (bedrockPlayer.level == otherPlayer.level) { + entry.updatePlayer(otherPlayer); } } }); diff --git a/src/main/java/org/geysermc/floodgate/util/FabricCommandUtil.java b/src/main/java/org/geysermc/floodgate/util/FabricCommandUtil.java index 29758e42..a976bca6 100644 --- a/src/main/java/org/geysermc/floodgate/util/FabricCommandUtil.java +++ b/src/main/java/org/geysermc/floodgate/util/FabricCommandUtil.java @@ -1,15 +1,9 @@ package org.geysermc.floodgate.util; import com.mojang.authlib.GameProfile; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import lombok.Getter; -import lombok.RequiredArgsConstructor; import me.lucko.fabric.api.permissions.v0.Permissions; -import net.kyori.adventure.platform.fabric.FabricServerAudiences; -import net.kyori.adventure.platform.fabric.PlayerLocales; import net.minecraft.commands.CommandSourceStack; import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.TextComponent; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.players.UserWhiteListEntry; @@ -17,110 +11,66 @@ import net.minecraft.world.entity.Entity; import org.checkerframework.checker.nullness.qual.NonNull; import org.geysermc.floodgate.api.FloodgateApi; import org.geysermc.floodgate.api.logger.FloodgateLogger; -import org.geysermc.floodgate.platform.command.TranslatableMessage; import org.geysermc.floodgate.platform.command.CommandUtil; import org.geysermc.floodgate.player.UserAudience; -import org.geysermc.floodgate.player.UserAudienceArgument; import java.util.*; -@RequiredArgsConstructor -public final class FabricCommandUtil implements CommandUtil { +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; - // This one also requires the server so it's bundled in - private static FabricServerAudiences ADVENTURE; - @Getter private final FloodgateApi api; - @Getter private final FloodgateLogger logger; - @Getter private final LanguageManager manager; + private final FloodgateLogger logger; + private UserAudience console; - @Override - public @NonNull UserAudience getAudience(@NonNull Object source) { - if (!(source instanceof CommandSourceStack commandSource)) { - throw new RuntimeException(); - } - - if (commandSource.getEntity() instanceof ServerPlayer) { - return getAudience0((ServerPlayer) commandSource.getEntity()); - } - - return new FabricUserAudience(null, manager.getDefaultLocale(), commandSource, this); + public FabricCommandUtil(LanguageManager manager, FloodgateApi api, FloodgateLogger logger) { + super(manager, api); + this.logger = logger; } @Override - public UserAudience getAudienceByUuid(@NonNull UUID uuid) { + public UserAudience getUserAudience(final @NonNull Object sourceObj) { + if (!(sourceObj instanceof CommandSourceStack stack)) { + throw new IllegalArgumentException(); + } + if (stack.getEntity() == null) { + if (console != null) { + return console; + } + return console = new UserAudience.ConsoleAudience(stack, this); + } + ServerPlayer player = stack.getPlayer(); + //Locale locale = PlayerLocales.locale(player); + return new UserAudience.PlayerAudience(player.getUUID(), player.getGameProfile().getName(), "en_US", + stack, this, true); + } + + @Override + protected String getUsernameFromSource(@NonNull Object source) { + return ((ServerPlayer) source).getGameProfile().getName(); + } + + @Override + protected UUID getUuidFromSource(@NonNull Object source) { + return ((ServerPlayer) source).getUUID(); + } + + @Override + public Object getPlayerByUuid(@NonNull UUID uuid) { ServerPlayer player = SERVER.getPlayerList().getPlayer(uuid); - if (player != null) { - return getAudience0(player); - } - return getOfflineAudienceByUuid(uuid); + return player != null ? player : uuid; } @Override - public UserAudience getAudienceByUsername(@NonNull String username) { + public Object getPlayerByUsername(@NonNull String username) { ServerPlayer player = SERVER.getPlayerList().getPlayerByName(username); - if (player != null) { - return getAudience0(player); - } - return getOfflineAudienceByUsername(username); - } - - private FabricUserAudience getAudience0(ServerPlayer player) { - // Apparently can be null even if Javadocs say otherwise - Locale locale = PlayerLocales.locale(player); - return new FabricUserAudience.NamedFabricUserAudience( - player.getName().getString(), - player.getUUID(), locale != null ? - locale.getLanguage().toLowerCase(Locale.ROOT) + "_" + locale.getCountry().toUpperCase(Locale.ROOT) : - manager.getDefaultLocale(), player.createCommandSourceStack(), this, true); + return player != null ? player : username; } @Override - public @NonNull UserAudience getOfflineAudienceByUuid(@NonNull UUID uuid) { - return new FabricUserAudience(uuid, null, null, this); - } - - @Override - public @NonNull UserAudience getOfflineAudienceByUsername(@NonNull String username) { - UUID uuid = null; - Optional profile = SERVER.getProfileCache().get(username); - if (profile.isPresent()) { - uuid = profile.get().getId(); - } - return new FabricUserAudience.NamedFabricUserAudience(username, uuid, username, null, this, false); - } - - @Override - public @NonNull Collection getOnlineUsernames(UserAudienceArgument.@NonNull PlayerType limitTo) { - List players = SERVER.getPlayerList().getPlayers(); - - Collection usernames = new ArrayList<>(); - switch (limitTo) { - case ALL_PLAYERS: - for (ServerPlayer player : players) { - usernames.add(player.getName().getString()); - } - break; - case ONLY_JAVA: - for (ServerPlayer player : players) { - if (!api.isFloodgatePlayer(player.getUUID())) { - usernames.add(player.getName().getString()); - } - } - break; - case ONLY_BEDROCK: - for (ServerPlayer player : players) { - if (api.isFloodgatePlayer(player.getUUID())) { - usernames.add(player.getName().getString()); - } - } - break; - default: - throw new IllegalStateException("Unknown PlayerType"); - } - return usernames; + protected Collection getOnlinePlayers() { + return SERVER.getPlayerList().getPlayers(); } @Override @@ -128,35 +78,12 @@ public final class FabricCommandUtil implements CommandUtil { return Permissions.check((Entity) player, permission); } - @Override - public Collection getOnlinePlayersWithPermission(String permission) { - List players = new ArrayList<>(); - for (ServerPlayer player : SERVER.getPlayerList().getPlayers()) { - if (hasPermission(player, permission)) { - players.add(player); - } - } - return players; - } - - @Override - public void sendMessage(Object player, String locale, TranslatableMessage message, Object... args) { - CommandSourceStack commandSource = (CommandSourceStack) player; - if (commandSource.getEntity() instanceof ServerPlayer) { - SERVER.execute(() -> ((ServerPlayer) commandSource.getEntity()) - .displayClientMessage(translateAndTransform(locale, message, args), false)); - } else { - // Console? - logger.info(message.translateMessage(manager, locale, args)); - } - } - @Override public void sendMessage(Object target, String message) { CommandSourceStack commandSource = (CommandSourceStack) target; if (commandSource.getEntity() instanceof ServerPlayer) { SERVER.execute(() -> ((ServerPlayer) commandSource.getEntity()) - .displayClientMessage(new TextComponent(message), false)); + .displayClientMessage(Component.literal(message), false)); } else { // Console? logger.info(message); @@ -164,8 +91,10 @@ public final class FabricCommandUtil implements CommandUtil { } @Override - public void kickPlayer(Object player, String locale, TranslatableMessage message, Object... args) { - getPlayer(player).connection.disconnect(translateAndTransform(locale, message, args)); + public void kickPlayer(Object o, String message) { + if (o instanceof ServerPlayer player) { + player.connection.disconnect(Component.literal(message)); + } } @Override @@ -182,26 +111,7 @@ public final class FabricCommandUtil implements CommandUtil { return true; } - private ServerPlayer getPlayer(Object instance) { - try { - CommandSourceStack source = (CommandSourceStack) instance; - return source.getPlayerOrException(); - } catch (ClassCastException | CommandSyntaxException exception) { - logger.error("Failed to cast {} as a player", instance.getClass().getName()); - throw new RuntimeException(); - } - } - - public Component translateAndTransform(String locale, TranslatableMessage message, Object... args) { - return new TextComponent(message.translateMessage(manager, locale, args)); - } - - public FabricServerAudiences getAdventure() { - return ADVENTURE; - } - - public static void setLaterVariables(MinecraftServer server, FabricServerAudiences adventure) { + public static void setServer(MinecraftServer server) { SERVER = server; - ADVENTURE = adventure; } } diff --git a/src/main/java/org/geysermc/floodgate/util/FabricPlatformUtils.java b/src/main/java/org/geysermc/floodgate/util/FabricPlatformUtils.java new file mode 100644 index 00000000..a355fe1f --- /dev/null +++ b/src/main/java/org/geysermc/floodgate/util/FabricPlatformUtils.java @@ -0,0 +1,28 @@ +package org.geysermc.floodgate.util; + +import net.minecraft.SharedConstants; +import net.minecraft.server.MinecraftServer; +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; + } + + @Override + public String minecraftVersion() { + return SharedConstants.getCurrentVersion().getName(); + } + + @Override + public String serverImplementationName() { + return "Fabric"; + } + + public static void setServer(MinecraftServer server) { + SERVER = server; + } +} diff --git a/src/main/java/org/geysermc/floodgate/util/FabricUserAudience.java b/src/main/java/org/geysermc/floodgate/util/FabricUserAudience.java deleted file mode 100644 index ba780c13..00000000 --- a/src/main/java/org/geysermc/floodgate/util/FabricUserAudience.java +++ /dev/null @@ -1,116 +0,0 @@ -package org.geysermc.floodgate.util; - -import lombok.RequiredArgsConstructor; -import me.lucko.fabric.api.permissions.v0.Permissions; -import net.kyori.adventure.audience.Audience; -import net.kyori.adventure.audience.ForwardingAudience; -import net.kyori.adventure.audience.MessageType; -import net.kyori.adventure.identity.Identity; -import net.kyori.adventure.text.Component; -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.server.level.ServerPlayer; -import org.checkerframework.checker.nullness.qual.NonNull; -import org.geysermc.floodgate.platform.command.TranslatableMessage; -import org.geysermc.floodgate.player.UserAudience; - -import java.util.UUID; - -@RequiredArgsConstructor -public class FabricUserAudience implements UserAudience, ForwardingAudience.Single { - private final UUID uuid; - private final String locale; - private final CommandSourceStack source; - private final FabricCommandUtil commandUtil; - - @Override - public @NonNull Audience audience() { - return commandUtil.getAdventure().audience(source); - } - - @Override - public @NonNull UUID uuid() { - return uuid; - } - - @Override - public @NonNull String username() { - if (source == null) { - return ""; - } - - return source.getTextName(); - } - - @Override - public @NonNull String locale() { - return locale; - } - - @Override - public @NonNull CommandSourceStack source() { - return source; - } - - @Override - public boolean hasPermission(@NonNull String permission) { - return Permissions.check(source, permission); - } - - @Override - public void sendMessage(@NonNull Identity source, @NonNull Component message, @NonNull MessageType type) { - commandUtil.getAdventure().audience(this.source).sendMessage(message); - } - - @Override - public void sendMessage(TranslatableMessage message, Object... args) { - commandUtil.sendMessage(this.source, this.locale, message, args); - } - - @Override - public void disconnect(@NonNull Component reason) { - if (source.getEntity() instanceof ServerPlayer) { - ((ServerPlayer) source.getEntity()).connection.disconnect( - commandUtil.getAdventure().toNative(reason) - ); - } - } - - @Override - public void disconnect(TranslatableMessage message, Object... args) { - if (source.getEntity() instanceof ServerPlayer) { - ((ServerPlayer) source.getEntity()).connection.disconnect( - commandUtil.translateAndTransform(this.locale, message, args) - ); - } - } - - /** - * Used whenever a name has been explicitly defined for us. Most helpful in offline players. - */ - public static final class NamedFabricUserAudience extends FabricUserAudience implements PlayerAudience { - private final String name; - private final boolean online; - - public NamedFabricUserAudience( - String name, - UUID uuid, - String locale, - CommandSourceStack source, - FabricCommandUtil commandUtil, - boolean online) { - super(uuid, locale, source, commandUtil); - this.name = name; - this.online = online; - } - - @Override - public @NonNull String username() { - return name; - } - - @Override - public boolean online() { - return online; - } - } -} diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index dd7781f5..7f2a1fcd 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -24,8 +24,8 @@ "floodgate.mixins.json" ], "depends": { - "fabricloader": ">=0.11.3", + "fabricloader": ">=0.14.6", "fabric": "*", - "minecraft": ">=1.18.2" + "minecraft": ">=1.19" } } diff --git a/src/main/resources/floodgate.accesswidener b/src/main/resources/floodgate.accesswidener index 4e7dcb8e..cad9dbdc 100644 --- a/src/main/resources/floodgate.accesswidener +++ b/src/main/resources/floodgate.accesswidener @@ -1,4 +1,6 @@ accessWidener v1 named # To change login state -accessible class net/minecraft/server/network/ServerLoginPacketListenerImpl$State \ No newline at end of file +accessible class net/minecraft/server/network/ServerLoginPacketListenerImpl$State +# For player skin refreshing +accessible class net/minecraft/server/level/ChunkMap$TrackedEntity \ No newline at end of file diff --git a/src/main/resources/floodgate.mixins.json b/src/main/resources/floodgate.mixins.json index 2b61e57f..8d29fb4d 100644 --- a/src/main/resources/floodgate.mixins.json +++ b/src/main/resources/floodgate.mixins.json @@ -4,10 +4,11 @@ "package": "org.geysermc.floodgate.mixin", "compatibilityLevel": "JAVA_16", "mixins": [ + "ChunkMapMixin", + "ClientIntentionPacketMixin", "ConnectionMixin", - "ServerLoginPacketListenerImplMixin", "ServerConnectionListenerMixin", - "ClientIntentionPacketMixin" + "ServerLoginPacketListenerImplMixin" ], "injectors": { "defaultRequire": 1