Skip to content

Commit

Permalink
fix(bluemap/auth): force fetch playerhead
Browse files Browse the repository at this point in the history
  • Loading branch information
Chicken committed Aug 20, 2024
1 parent 8ea65a7 commit 0297fd3
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* This file is part of BMUtils, licensed under the MPL2 License (MPL).
* Please keep tabs on https://github.com/TechnicJelle/BMUtils for updates.
*
* Copyright (c) TechnicJelle <https://technicjelle.com>
* Copyright (c) contributors
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/

package codes.antti.auth.bluemap.integration;

import de.bluecolored.bluemap.api.BlueMapAPI;
import de.bluecolored.bluemap.api.BlueMapMap;
import de.bluecolored.bluemap.api.plugin.SkinProvider;
import org.jetbrains.annotations.NotNull;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Optional;
import java.util.UUID;

/**
* Utility functions for BlueMap skins and playerheads
*/
public class BMSkin {
private BMSkin() {
throw new IllegalStateException("Utility class");
}

private static final String FALLBACK_ICON = "assets/steve.png";

/**
* Gets the URL to a player head icon for a specific map.<br>
* If the icon doesn't exist yet, it will be created.
*
* @param blueMapAPI The BlueMapAPI instance
* @param playerUUID The player to get the head of
* @param blueMapMap The map to get the head for (each map has its own playerheads folder)
* @return The URL to the player head, relative to BlueMap's web root,<br>
* or a Steve head if the head couldn't be found
*/
public static String getPlayerHeadIconAddress(
final @NotNull BlueMapAPI blueMapAPI,
final @NotNull UUID playerUUID,
final @NotNull BlueMapMap blueMapMap
) {
final String assetName = "playerheads/" + playerUUID + ".png";

try {
if (!blueMapMap.getAssetStorage().assetExists(assetName)) {
createPlayerHead(blueMapAPI, playerUUID, assetName, blueMapMap);
}
} catch (IOException e) {
return FALLBACK_ICON;
}

return blueMapMap.getAssetStorage().getAssetUrl(assetName);
}

/**
* For when BlueMap doesn't have an icon for this player yet, so we need to make it create one.
*/
private static void createPlayerHead(
final @NotNull BlueMapAPI blueMapAPI,
final @NotNull UUID playerUUID,
final @NotNull String assetName,
final @NotNull BlueMapMap map
) throws IOException {
final SkinProvider skinProvider = blueMapAPI.getPlugin().getSkinProvider();
try {
final Optional<BufferedImage> oImgSkin = skinProvider.load(playerUUID);
if (oImgSkin.isEmpty()) {
throw new IOException(playerUUID + " doesn't have a skin");
}

try (OutputStream out = map.getAssetStorage().writeAsset(assetName)) {
final BufferedImage head = blueMapAPI.getPlugin().getPlayerMarkerIconFactory()
.apply(playerUUID, oImgSkin.get());
ImageIO.write(head, "png", out);
} catch (IOException e) {
throw new IOException("Failed to write " + playerUUID + "'s head to asset-storage", e);
}
} catch (IOException e) {
throw new IOException("Failed to load skin for player " + playerUUID, e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import codes.antti.auth.common.http.WebServer;
import com.google.gson.JsonObject;
import de.bluecolored.bluemap.api.BlueMapAPI;
import de.bluecolored.bluemap.api.BlueMapMap;
import org.bukkit.configuration.Configuration;
import org.bukkit.plugin.java.JavaPlugin;

Expand All @@ -13,6 +14,7 @@
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;

public final class BlueMapAuthIntegrationPlugin extends JavaPlugin {
Expand Down Expand Up @@ -54,6 +56,28 @@ public void onEnable() {
request.respond(200);
});

this.http.get("/playerheads/*", request -> {
String[] parts = request.getPath().split("/");
if (parts.length != 4) {
request.respond(400);
return;
}
String mapId = parts[2];
UUID uuid;
try {
uuid = UUID.fromString(parts[3]);
} catch (IllegalArgumentException ex) {
request.respond(400);
return;
}
Optional<BlueMapMap> map = api.getMap(mapId);
if (map.isEmpty()) {
request.respond(404);
return;
}
request.redirect(301, "../../../../" + BMSkin.getPlayerHeadIconAddress(api, uuid, map.get()));
});

this.http.start();
getLogger().info("Webserver bound to " + this.http.getAddress());

Expand Down
4 changes: 2 additions & 2 deletions BlueMap/Integration/src/main/resources/bluemap-integration.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ void async function() {
userTemplate.innerHTML = `
<div style="display: flex; flex-direction: row; align-items: center; padding: .1em .5em;">
<img
src="./maps/${window.bluemap.mapViewer.data.map.id}/assets/playerheads/${uuid}.png"
src="./addons/integration/playerheads/${window.bluemap.mapViewer.data.map.id}/${uuid}"
style="width: 28px; height: 28px; margin-right: 8px; border-radius: 2px;"
alt="Your playerhead" />
${username}
Expand All @@ -60,7 +60,7 @@ void async function() {
if (uuid) {
buttonList.appendChild(logOutButton);
buttonList.appendChild(logOutAllButton);
userElement.children.item(0).src = `./maps/${window.bluemap.mapViewer.data.map.id}/assets/playerheads/${uuid}.png`
userElement.children.item(0).src = `./addons/integration/playerheads/${window.bluemap.mapViewer.data.map.id}/${uuid}`
buttonList.insertBefore(userElement, buttonList.childNodes[0]);
} else {
buttonList.appendChild(logInButton);
Expand Down

0 comments on commit 0297fd3

Please sign in to comment.