forked from SteamWar/SteamWar
Resend replay player tab entry when skin arrives
RPlayer requests the skin asynchronously, so the first tab list packet is usually sent without textures and viewers already in range kept the default skin. Re-send despawn/delist/list/spawn to the current viewers once the skin response is received.
This commit is contained in:
@@ -141,6 +141,22 @@ public class REntityServer implements Listener {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-sends list and spawn packets of an already added entity to all current viewers,
|
||||
* e.g. when information that is part of the tab list entry changed after the entity was added.
|
||||
*/
|
||||
void refreshEntity(REntity entity) {
|
||||
if (!entityMap.containsKey(entity.entityId)) return;
|
||||
|
||||
for (Player player : players.getOrDefault(entityToId(entity), emptyPlayers)) {
|
||||
Consumer<Object> sink = packet -> TinyProtocol.instance.sendPacket(player, packet);
|
||||
if (!entity.isHidden()) entity.despawn(sink);
|
||||
entity.delist(sink);
|
||||
entity.list(sink);
|
||||
if (!entity.isHidden()) entity.spawn(sink);
|
||||
}
|
||||
}
|
||||
|
||||
void removeEntity(REntity entity) {
|
||||
entity.despawn(packet -> updateEntity(entity, packet));
|
||||
removeEntityFromChunk(entity);
|
||||
|
||||
@@ -76,10 +76,20 @@ public class RPlayer extends REntity implements RInteractableEntity<RPlayer> {
|
||||
}
|
||||
|
||||
private GameProfile saved;
|
||||
private boolean awaitingSkin = false;
|
||||
|
||||
@Override
|
||||
void list(Consumer<Object> packetSink) {
|
||||
saved = getGameProfile();
|
||||
if (saved.getProperties().isEmpty() && !awaitingSkin) {
|
||||
// The skin is requested asynchronously, so it is usually not available yet when the entity is created.
|
||||
// Without a refresh, players that already see this entity would keep the default skin.
|
||||
awaitingSkin = true;
|
||||
CoreNetworkHandler.onSkinReceived(actualUUID, () -> {
|
||||
awaitingSkin = false;
|
||||
server.refreshEntity(this);
|
||||
});
|
||||
}
|
||||
packetSink.accept(ProtocolWrapper.playerInfoPacketConstructor(ProtocolWrapper.PlayerInfoAction.ADD, saved, GameMode.CREATIVE));
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ package de.steamwar.network;
|
||||
|
||||
import com.mojang.authlib.properties.Property;
|
||||
import de.steamwar.core.BountifulWrapper;
|
||||
import de.steamwar.core.Core;
|
||||
import de.steamwar.network.handlers.InventoryHandler;
|
||||
import de.steamwar.network.packets.PacketHandler;
|
||||
import de.steamwar.network.packets.common.PlayerSkinResponsePacket;
|
||||
@@ -31,8 +32,11 @@ import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
public class CoreNetworkHandler extends PacketHandler {
|
||||
|
||||
@@ -85,9 +89,23 @@ public class CoreNetworkHandler extends PacketHandler {
|
||||
}
|
||||
};
|
||||
|
||||
private static final Map<UUID, List<Runnable>> SKIN_LISTENERS = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* Runs the given callback on the main thread once the skin of the given player has been received.
|
||||
*/
|
||||
public static void onSkinReceived(UUID uuid, Runnable callback) {
|
||||
SKIN_LISTENERS.computeIfAbsent(uuid, __ -> new CopyOnWriteArrayList<>()).add(callback);
|
||||
}
|
||||
|
||||
@Handler
|
||||
public void handlePlayerSkinResponse(PlayerSkinResponsePacket packet) {
|
||||
if (!SKIN_DATA_PROMISES.containsKey(packet.getUuid())) return;
|
||||
SKIN_DATA_PROMISES.put(packet.getUuid(), new Property("textures", packet.getSkin(), packet.getSignature()));
|
||||
|
||||
Bukkit.getScheduler().runTask(Core.getInstance(), () -> {
|
||||
List<Runnable> listeners = SKIN_LISTENERS.remove(packet.getUuid());
|
||||
if (listeners != null) listeners.forEach(Runnable::run);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user