1
0
mirror of https://github.com/GeyserMC/Floodgate.git synced 2025-12-30 20:29:30 +00:00

Update for 1.19

With thanks to Kastle.
This commit is contained in:
Camotoy
2022-06-14 16:09:01 -04:00
parent 5d5864db5a
commit 7482ac791b
15 changed files with 138 additions and 354 deletions

View File

@@ -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"
}

View File

@@ -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

View File

@@ -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(),

View File

@@ -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());
}
}

View File

@@ -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()

View File

@@ -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<ChunkMap.TrackedEntity> getEntityMap();
}

View File

@@ -19,7 +19,7 @@ public final class FabricCommandModule extends CommandModule {
public CommandManager<UserAudience> commandManager(CommandUtil commandUtil) {
FabricCommandManager<UserAudience, CommandSourceStack> commandManager = new FabricServerCommandManager<>(
CommandExecutionCoordinator.simpleCoordinator(),
commandUtil::getAudience,
commandUtil::getUserAudience,
audience -> (CommandSourceStack) audience.source()
);
commandManager.registerCommandPreProcessor(new FloodgateCommandPreprocessor<>(commandUtil));

View File

@@ -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

View File

@@ -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<AttributeInstance> 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<Pair<EquipmentSlot, ItemStack>> 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);
}
}
});

View File

@@ -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<GameProfile> 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<String> getOnlineUsernames(UserAudienceArgument.@NonNull PlayerType limitTo) {
List<ServerPlayer> players = SERVER.getPlayerList().getPlayers();
Collection<String> 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<Object> getOnlinePlayersWithPermission(String permission) {
List<Object> 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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}
}

View File

@@ -24,8 +24,8 @@
"floodgate.mixins.json"
],
"depends": {
"fabricloader": ">=0.11.3",
"fabricloader": ">=0.14.6",
"fabric": "*",
"minecraft": ">=1.18.2"
"minecraft": ">=1.19"
}
}

View File

@@ -1,4 +1,6 @@
accessWidener v1 named
# To change login state
accessible class net/minecraft/server/network/ServerLoginPacketListenerImpl$State
accessible class net/minecraft/server/network/ServerLoginPacketListenerImpl$State
# For player skin refreshing
accessible class net/minecraft/server/level/ChunkMap$TrackedEntity

View File

@@ -4,10 +4,11 @@
"package": "org.geysermc.floodgate.mixin",
"compatibilityLevel": "JAVA_16",
"mixins": [
"ChunkMapMixin",
"ClientIntentionPacketMixin",
"ConnectionMixin",
"ServerLoginPacketListenerImplMixin",
"ServerConnectionListenerMixin",
"ClientIntentionPacketMixin"
"ServerLoginPacketListenerImplMixin"
],
"injectors": {
"defaultRequire": 1