108 lines
3.6 KiB
Java
108 lines
3.6 KiB
Java
package org.warp.cachedplayerheads;
|
|
|
|
import com.google.common.io.ByteArrayDataInput;
|
|
import com.google.common.io.ByteArrayDataOutput;
|
|
import com.google.common.io.ByteStreams;
|
|
import java.util.UUID;
|
|
import java.util.concurrent.CompletableFuture;
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
import java.util.concurrent.Executors;
|
|
import java.util.concurrent.ScheduledExecutorService;
|
|
import java.util.concurrent.TimeUnit;
|
|
import java.util.concurrent.TimeoutException;
|
|
import org.bukkit.Bukkit;
|
|
import org.bukkit.configuration.ConfigurationSection;
|
|
import org.bukkit.entity.Player;
|
|
import org.bukkit.plugin.Plugin;
|
|
import org.bukkit.plugin.messaging.PluginMessageListener;
|
|
import org.jetbrains.annotations.Nullable;
|
|
|
|
public class BungeeAPI implements PluginMessageListener {
|
|
|
|
private final Plugin playerheads;
|
|
private final ConcurrentHashMap<UUID, CompletableFuture<String>> requests = new ConcurrentHashMap<>();
|
|
|
|
private static final ScheduledExecutorService executor;
|
|
|
|
static {
|
|
executor = Executors.newSingleThreadScheduledExecutor();
|
|
}
|
|
|
|
public BungeeAPI(Plugin playerheads) {
|
|
this.playerheads = playerheads;
|
|
|
|
playerheads.getServer().getMessenger()
|
|
.registerIncomingPluginChannel(playerheads, "cachedplayerheads:channel", this);
|
|
playerheads.getServer().getMessenger()
|
|
.registerOutgoingPluginChannel(playerheads, "cachedplayerheads:channel");
|
|
}
|
|
|
|
private boolean checkIfBungee() {
|
|
@Nullable ConfigurationSection settings = playerheads
|
|
.getServer()
|
|
.spigot()
|
|
.getConfig()
|
|
.getConfigurationSection("settings");
|
|
if (settings == null || !settings.getBoolean("settings.bungeecord")) {
|
|
playerheads.getLogger().severe("This server is not BungeeCord.");
|
|
return false;
|
|
} else {
|
|
playerheads.getLogger().severe("This server is BungeeCord.");
|
|
return true;
|
|
}
|
|
}
|
|
|
|
public CompletableFuture<String> getPlayerTexture(String playerName) {
|
|
ByteArrayDataOutput out = ByteStreams.newDataOutput();
|
|
out.writeUTF("PlayerTextureRequest");
|
|
UUID reqUUID = UUID.randomUUID();
|
|
out.writeLong(reqUUID.getMostSignificantBits());
|
|
out.writeLong(reqUUID.getLeastSignificantBits());
|
|
out.writeUTF(playerName);
|
|
|
|
|
|
CompletableFuture<String> futureResult = new CompletableFuture<>();
|
|
requests.put(reqUUID, futureResult);
|
|
|
|
try {
|
|
System.out.println("Asking player texture. Request: " + reqUUID);
|
|
Bukkit.getServer().sendPluginMessage(playerheads, "cachedplayerheads:channel", out.toByteArray());
|
|
} catch (Exception ex) {
|
|
requests.remove(reqUUID);
|
|
throw ex;
|
|
}
|
|
|
|
CompletableFuture<String> timeoutFuture = new CompletableFuture<>();
|
|
executor.schedule(() -> {
|
|
requests.remove(reqUUID);
|
|
timeoutFuture.completeExceptionally(new TimeoutException());
|
|
}, 30, TimeUnit.SECONDS);
|
|
return CompletableFuture.anyOf(futureResult, timeoutFuture).thenApply(x -> (String) x);
|
|
}
|
|
|
|
@Override
|
|
public void onPluginMessageReceived(String channel, Player player, byte[] message) {
|
|
if (!channel.equalsIgnoreCase("cachedplayerheads:channel")) {
|
|
return;
|
|
}
|
|
ByteArrayDataInput in = ByteStreams.newDataInput(message);
|
|
String subchannel = in.readUTF();
|
|
if (subchannel.equals("PlayerTextureResponse")) {
|
|
long msb = in.readLong();
|
|
long lsb = in.readLong();
|
|
boolean hasString = in.readBoolean();
|
|
String skinData = hasString ? in.readUTF() : null;
|
|
UUID reqUUID = new UUID(msb, lsb);
|
|
System.out.println("Received player texture. Request: " + reqUUID);
|
|
CompletableFuture<String> req = requests.get(reqUUID);
|
|
if (req != null) {
|
|
req.complete(skinData);
|
|
} else {
|
|
System.out.println("Received response for unknown request: " + reqUUID);
|
|
}
|
|
} else {
|
|
System.err.println("Invalid subchannel: " + subchannel);
|
|
}
|
|
}
|
|
}
|