217 lines
		
	
	
	
		
			8.5 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			217 lines
		
	
	
	
		
			8.5 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
| package net.minecraft.network.protocol.game;
 | |
| 
 | |
| import com.google.common.base.MoreObjects;
 | |
| import com.mojang.authlib.GameProfile;
 | |
| import java.util.Collection;
 | |
| import java.util.EnumSet;
 | |
| import java.util.List;
 | |
| import java.util.Objects;
 | |
| import java.util.UUID;
 | |
| import net.minecraft.Optionull;
 | |
| import net.minecraft.network.FriendlyByteBuf;
 | |
| import net.minecraft.network.RegistryFriendlyByteBuf;
 | |
| import net.minecraft.network.chat.Component;
 | |
| import net.minecraft.network.chat.ComponentSerialization;
 | |
| import net.minecraft.network.chat.RemoteChatSession;
 | |
| import net.minecraft.network.codec.ByteBufCodecs;
 | |
| import net.minecraft.network.codec.StreamCodec;
 | |
| import net.minecraft.network.protocol.Packet;
 | |
| import net.minecraft.network.protocol.PacketType;
 | |
| import net.minecraft.server.level.ServerPlayer;
 | |
| import net.minecraft.world.entity.player.PlayerModelPart;
 | |
| import net.minecraft.world.level.GameType;
 | |
| import org.jetbrains.annotations.Nullable;
 | |
| 
 | |
| public class ClientboundPlayerInfoUpdatePacket implements Packet<ClientGamePacketListener> {
 | |
| 	public static final StreamCodec<RegistryFriendlyByteBuf, ClientboundPlayerInfoUpdatePacket> STREAM_CODEC = Packet.codec(
 | |
| 		ClientboundPlayerInfoUpdatePacket::write, ClientboundPlayerInfoUpdatePacket::new
 | |
| 	);
 | |
| 	private final EnumSet<ClientboundPlayerInfoUpdatePacket.Action> actions;
 | |
| 	private final List<ClientboundPlayerInfoUpdatePacket.Entry> entries;
 | |
| 
 | |
| 	public ClientboundPlayerInfoUpdatePacket(EnumSet<ClientboundPlayerInfoUpdatePacket.Action> actions, Collection<ServerPlayer> players) {
 | |
| 		this.actions = actions;
 | |
| 		this.entries = players.stream().map(ClientboundPlayerInfoUpdatePacket.Entry::new).toList();
 | |
| 	}
 | |
| 
 | |
| 	public ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.Action action, ServerPlayer player) {
 | |
| 		this.actions = EnumSet.of(action);
 | |
| 		this.entries = List.of(new ClientboundPlayerInfoUpdatePacket.Entry(player));
 | |
| 	}
 | |
| 
 | |
| 	public static ClientboundPlayerInfoUpdatePacket createPlayerInitializing(Collection<ServerPlayer> players) {
 | |
| 		EnumSet<ClientboundPlayerInfoUpdatePacket.Action> enumSet = EnumSet.of(
 | |
| 			ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER,
 | |
| 			ClientboundPlayerInfoUpdatePacket.Action.INITIALIZE_CHAT,
 | |
| 			ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE,
 | |
| 			ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LISTED,
 | |
| 			ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LATENCY,
 | |
| 			ClientboundPlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME,
 | |
| 			ClientboundPlayerInfoUpdatePacket.Action.UPDATE_HAT,
 | |
| 			ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LIST_ORDER
 | |
| 		);
 | |
| 		return new ClientboundPlayerInfoUpdatePacket(enumSet, players);
 | |
| 	}
 | |
| 
 | |
| 	private ClientboundPlayerInfoUpdatePacket(RegistryFriendlyByteBuf buffer) {
 | |
| 		this.actions = buffer.readEnumSet(ClientboundPlayerInfoUpdatePacket.Action.class);
 | |
| 		this.entries = buffer.readList(friendlyByteBuf -> {
 | |
| 			ClientboundPlayerInfoUpdatePacket.EntryBuilder entryBuilder = new ClientboundPlayerInfoUpdatePacket.EntryBuilder(friendlyByteBuf.readUUID());
 | |
| 
 | |
| 			for (ClientboundPlayerInfoUpdatePacket.Action action : this.actions) {
 | |
| 				action.reader.read(entryBuilder, (RegistryFriendlyByteBuf)friendlyByteBuf);
 | |
| 			}
 | |
| 
 | |
| 			return entryBuilder.build();
 | |
| 		});
 | |
| 	}
 | |
| 
 | |
| 	private void write(RegistryFriendlyByteBuf buffer) {
 | |
| 		buffer.writeEnumSet(this.actions, ClientboundPlayerInfoUpdatePacket.Action.class);
 | |
| 		buffer.writeCollection(this.entries, (friendlyByteBuf, entry) -> {
 | |
| 			friendlyByteBuf.writeUUID(entry.profileId());
 | |
| 
 | |
| 			for (ClientboundPlayerInfoUpdatePacket.Action action : this.actions) {
 | |
| 				action.writer.write((RegistryFriendlyByteBuf)friendlyByteBuf, entry);
 | |
| 			}
 | |
| 		});
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public PacketType<ClientboundPlayerInfoUpdatePacket> type() {
 | |
| 		return GamePacketTypes.CLIENTBOUND_PLAYER_INFO_UPDATE;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Passes this Packet on to the PacketListener for processing.
 | |
| 	 */
 | |
| 	public void handle(ClientGamePacketListener handler) {
 | |
| 		handler.handlePlayerInfoUpdate(this);
 | |
| 	}
 | |
| 
 | |
| 	public EnumSet<ClientboundPlayerInfoUpdatePacket.Action> actions() {
 | |
| 		return this.actions;
 | |
| 	}
 | |
| 
 | |
| 	public List<ClientboundPlayerInfoUpdatePacket.Entry> entries() {
 | |
| 		return this.entries;
 | |
| 	}
 | |
| 
 | |
| 	public List<ClientboundPlayerInfoUpdatePacket.Entry> newEntries() {
 | |
| 		return this.actions.contains(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER) ? this.entries : List.of();
 | |
| 	}
 | |
| 
 | |
| 	public String toString() {
 | |
| 		return MoreObjects.toStringHelper(this).add("actions", this.actions).add("entries", this.entries).toString();
 | |
| 	}
 | |
| 
 | |
| 	public static enum Action {
 | |
| 		ADD_PLAYER((entryBuilder, registryFriendlyByteBuf) -> {
 | |
| 			GameProfile gameProfile = new GameProfile(entryBuilder.profileId, registryFriendlyByteBuf.readUtf(16));
 | |
| 			gameProfile.getProperties().putAll(ByteBufCodecs.GAME_PROFILE_PROPERTIES.decode(registryFriendlyByteBuf));
 | |
| 			entryBuilder.profile = gameProfile;
 | |
| 		}, (registryFriendlyByteBuf, entry) -> {
 | |
| 			GameProfile gameProfile = (GameProfile)Objects.requireNonNull(entry.profile());
 | |
| 			registryFriendlyByteBuf.writeUtf(gameProfile.getName(), 16);
 | |
| 			ByteBufCodecs.GAME_PROFILE_PROPERTIES.encode(registryFriendlyByteBuf, gameProfile.getProperties());
 | |
| 		}),
 | |
| 		INITIALIZE_CHAT(
 | |
| 			(entryBuilder, registryFriendlyByteBuf) -> entryBuilder.chatSession = registryFriendlyByteBuf.readNullable(RemoteChatSession.Data::read),
 | |
| 			(registryFriendlyByteBuf, entry) -> registryFriendlyByteBuf.writeNullable(entry.chatSession, RemoteChatSession.Data::write)
 | |
| 		),
 | |
| 		UPDATE_GAME_MODE(
 | |
| 			(entryBuilder, registryFriendlyByteBuf) -> entryBuilder.gameMode = GameType.byId(registryFriendlyByteBuf.readVarInt()),
 | |
| 			(registryFriendlyByteBuf, entry) -> registryFriendlyByteBuf.writeVarInt(entry.gameMode().getId())
 | |
| 		),
 | |
| 		UPDATE_LISTED(
 | |
| 			(entryBuilder, registryFriendlyByteBuf) -> entryBuilder.listed = registryFriendlyByteBuf.readBoolean(),
 | |
| 			(registryFriendlyByteBuf, entry) -> registryFriendlyByteBuf.writeBoolean(entry.listed())
 | |
| 		),
 | |
| 		UPDATE_LATENCY(
 | |
| 			(entryBuilder, registryFriendlyByteBuf) -> entryBuilder.latency = registryFriendlyByteBuf.readVarInt(),
 | |
| 			(registryFriendlyByteBuf, entry) -> registryFriendlyByteBuf.writeVarInt(entry.latency())
 | |
| 		),
 | |
| 		UPDATE_DISPLAY_NAME(
 | |
| 			(entryBuilder, registryFriendlyByteBuf) -> entryBuilder.displayName = FriendlyByteBuf.readNullable(
 | |
| 				registryFriendlyByteBuf, ComponentSerialization.TRUSTED_STREAM_CODEC
 | |
| 			),
 | |
| 			(registryFriendlyByteBuf, entry) -> FriendlyByteBuf.writeNullable(registryFriendlyByteBuf, entry.displayName(), ComponentSerialization.TRUSTED_STREAM_CODEC)
 | |
| 		),
 | |
| 		UPDATE_LIST_ORDER(
 | |
| 			(entryBuilder, registryFriendlyByteBuf) -> entryBuilder.listOrder = registryFriendlyByteBuf.readVarInt(),
 | |
| 			(registryFriendlyByteBuf, entry) -> registryFriendlyByteBuf.writeVarInt(entry.listOrder)
 | |
| 		),
 | |
| 		UPDATE_HAT(
 | |
| 			(entryBuilder, registryFriendlyByteBuf) -> entryBuilder.showHat = registryFriendlyByteBuf.readBoolean(),
 | |
| 			(registryFriendlyByteBuf, entry) -> registryFriendlyByteBuf.writeBoolean(entry.showHat)
 | |
| 		);
 | |
| 
 | |
| 		final ClientboundPlayerInfoUpdatePacket.Action.Reader reader;
 | |
| 		final ClientboundPlayerInfoUpdatePacket.Action.Writer writer;
 | |
| 
 | |
| 		private Action(final ClientboundPlayerInfoUpdatePacket.Action.Reader reader, final ClientboundPlayerInfoUpdatePacket.Action.Writer writer) {
 | |
| 			this.reader = reader;
 | |
| 			this.writer = writer;
 | |
| 		}
 | |
| 
 | |
| 		public interface Reader {
 | |
| 			void read(ClientboundPlayerInfoUpdatePacket.EntryBuilder entryBuilder, RegistryFriendlyByteBuf registryFriendlyByteBuf);
 | |
| 		}
 | |
| 
 | |
| 		public interface Writer {
 | |
| 			void write(RegistryFriendlyByteBuf registryFriendlyByteBuf, ClientboundPlayerInfoUpdatePacket.Entry entry);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	public record Entry(
 | |
| 		UUID profileId,
 | |
| 		@Nullable GameProfile profile,
 | |
| 		boolean listed,
 | |
| 		int latency,
 | |
| 		GameType gameMode,
 | |
| 		@Nullable Component displayName,
 | |
| 		boolean showHat,
 | |
| 		int listOrder,
 | |
| 		@Nullable RemoteChatSession.Data chatSession
 | |
| 	) {
 | |
| 
 | |
| 		Entry(ServerPlayer player) {
 | |
| 			this(
 | |
| 				player.getUUID(),
 | |
| 				player.getGameProfile(),
 | |
| 				true,
 | |
| 				player.connection.latency(),
 | |
| 				player.gameMode(),
 | |
| 				player.getTabListDisplayName(),
 | |
| 				player.isModelPartShown(PlayerModelPart.HAT),
 | |
| 				player.getTabListOrder(),
 | |
| 				Optionull.map(player.getChatSession(), RemoteChatSession::asData)
 | |
| 			);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	static class EntryBuilder {
 | |
| 		final UUID profileId;
 | |
| 		@Nullable
 | |
| 		GameProfile profile;
 | |
| 		boolean listed;
 | |
| 		int latency;
 | |
| 		GameType gameMode = GameType.DEFAULT_MODE;
 | |
| 		@Nullable
 | |
| 		Component displayName;
 | |
| 		boolean showHat;
 | |
| 		int listOrder;
 | |
| 		@Nullable
 | |
| 		RemoteChatSession.Data chatSession;
 | |
| 
 | |
| 		EntryBuilder(UUID profileId) {
 | |
| 			this.profileId = profileId;
 | |
| 		}
 | |
| 
 | |
| 		ClientboundPlayerInfoUpdatePacket.Entry build() {
 | |
| 			return new ClientboundPlayerInfoUpdatePacket.Entry(
 | |
| 				this.profileId, this.profile, this.listed, this.latency, this.gameMode, this.displayName, this.showHat, this.listOrder, this.chatSession
 | |
| 			);
 | |
| 		}
 | |
| 	}
 | |
| }
 |