package protocolsupport.protocol.packet.middleimpl.clientbound.play.v_4_5_6_7;

import java.util.Arrays;
import java.util.HashMap;
import java.util.UUID;

import protocolsupport.api.ProtocolVersion;
import protocolsupport.protocol.packet.ClientBoundPacket;
import protocolsupport.protocol.packet.middle.clientbound.play.MiddlePlayerListSetEntry;
import protocolsupport.protocol.packet.middleimpl.ClientBoundPacketData;
import protocolsupport.protocol.serializer.StringSerializer;
import protocolsupport.protocol.storage.netcache.PlayerListCache;
import protocolsupport.utils.Utils;
import protocolsupport.utils.recyclable.RecyclableArrayList;
import protocolsupport.utils.recyclable.RecyclableCollection;

public class PlayerListSetEntry extends MiddlePlayerListSetEntry {

	protected final HashMap<UUID, String> oldNames = new HashMap<>();

	@Override
	public boolean postFromServerRead() {
		PlayerListCache plcache = cache.getPlayerListCache();
		oldNames.clear();
		Arrays.stream(infos).forEach(info -> oldNames.put(info.uuid, plcache.getEntry(info.uuid).getName(cache.getAttributesCache().getLocale())));
		return super.postFromServerRead();
	}

	@Override
	public RecyclableCollection<ClientBoundPacketData> toData() {
		ProtocolVersion version = connection.getVersion();
		RecyclableArrayList<ClientBoundPacketData> packets = RecyclableArrayList.create();
		switch (action) {
			case ADD: {
				Arrays.stream(infos).forEach(info -> packets.add(create(info.getName(cache.getAttributesCache().getLocale()), (short) info.ping, true, version)));
				break;
			}
			case DISPLAY_NAME: {
				Arrays.stream(infos).forEach(info -> {
					packets.add(create(oldNames.get(info.uuid), (short) info.ping, false, version));
					packets.add(create(info.getName(cache.getAttributesCache().getLocale()), (short) info.ping, true, version));
				});
				break;
			}
			case REMOVE: {
				Arrays.stream(infos).forEach(info -> packets.add(create(oldNames.get(info.uuid), (short) info.ping, false, version)));
				break;
			}
			default: {
				break;
			}
		}
		return packets;
	}

	protected static ClientBoundPacketData create(String name, short ping, boolean add, ProtocolVersion version) {
		ClientBoundPacketData serializer = ClientBoundPacketData.create(ClientBoundPacket.PLAY_PLAYER_INFO_ID);
		StringSerializer.writeString(serializer, version, Utils.clampString(name, 16));
		serializer.writeBoolean(add);
		serializer.writeShort(ping);
		return serializer;
	}

}

@@ -1443,32 +1443,41 @@
 kets.add(create(
+version, 
 info.getName(cac
@@ -1505,32 +1505,38 @@
 ().getLocale()),
+ true,
  (short) info.pi
@@ -1537,31 +1537,16 @@
 nfo.ping
-, true, version
 )));%0A%09%09%09
@@ -1641,32 +1641,41 @@
 kets.add(create(
+version, 
 oldNames.get(inf
@@ -1674,32 +1674,39 @@
 .get(info.uuid),
+ false,
  (short) info.pi
@@ -1707,32 +1707,16 @@
 nfo.ping
-, false, version
 ));%0A%09%09%09%09
@@ -1735,16 +1735,25 @@
 (create(
+version, 
 info.get
@@ -1797,16 +1797,22 @@
 cale()),
+ true,
  (short)
@@ -1825,23 +1825,8 @@
 ping
-, true, version
 ));%0A
@@ -1927,16 +1927,25 @@
 (create(
+version, 
 oldNames
@@ -1960,16 +1960,23 @@
 o.uuid),
+ false,
  (short)
@@ -1989,24 +1989,162 @@
 ping
-, false, version
+)));%0A%09%09%09%09break;%0A%09%09%09%7D%0A%09%09%09case PING: %7B%0A%09%09%09%09Arrays.stream(infos).forEach(info -%3E packets.add(create(version, oldNames.get(info.uuid), true, (short) info.ping
 )));
@@ -2267,69 +2267,69 @@
 ate(
-String name, short ping, boolean add, ProtocolVersion version
+ProtocolVersion version, String name, boolean add, short ping
 ) %7B%0A

Update player list ping for legacy clients too.