2020-08-07 14:17:48 +02:00
|
|
|
/*
|
|
|
|
* This file is part of BlueMap, licensed under the MIT License (MIT).
|
|
|
|
*
|
|
|
|
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
|
|
|
|
* Copyright (c) contributors
|
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
|
|
* in the Software without restriction, including without limitation the rights
|
|
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
|
|
* furnished to do so, subject to the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice shall be included in
|
|
|
|
* all copies or substantial portions of the Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
* THE SOFTWARE.
|
|
|
|
*/
|
|
|
|
package de.bluecolored.bluemap.common.plugin.skins;
|
|
|
|
|
2022-07-24 12:10:00 +02:00
|
|
|
import de.bluecolored.bluemap.api.debug.DebugDump;
|
2022-12-13 16:54:31 +01:00
|
|
|
import de.bluecolored.bluemap.api.plugin.PlayerIconFactory;
|
|
|
|
import de.bluecolored.bluemap.api.plugin.SkinProvider;
|
|
|
|
import de.bluecolored.bluemap.common.plugin.Plugin;
|
|
|
|
import de.bluecolored.bluemap.common.serverinterface.ServerEventListener;
|
|
|
|
import de.bluecolored.bluemap.core.BlueMap;
|
|
|
|
import de.bluecolored.bluemap.core.logger.Logger;
|
|
|
|
import de.bluecolored.bluemap.core.map.BmMap;
|
2021-03-28 13:25:39 +02:00
|
|
|
|
2022-12-13 16:54:31 +01:00
|
|
|
import javax.imageio.ImageIO;
|
|
|
|
import java.awt.image.BufferedImage;
|
2021-03-28 13:25:39 +02:00
|
|
|
import java.io.IOException;
|
2022-12-13 16:54:31 +01:00
|
|
|
import java.io.OutputStream;
|
2020-08-07 14:17:48 +02:00
|
|
|
import java.util.Map;
|
2022-12-13 16:54:31 +01:00
|
|
|
import java.util.Objects;
|
2020-08-07 14:17:48 +02:00
|
|
|
import java.util.UUID;
|
2022-12-13 16:54:31 +01:00
|
|
|
import java.util.concurrent.CompletableFuture;
|
|
|
|
import java.util.concurrent.CompletionException;
|
2020-08-07 14:17:48 +02:00
|
|
|
import java.util.concurrent.ConcurrentHashMap;
|
2022-12-13 16:54:31 +01:00
|
|
|
import java.util.concurrent.TimeUnit;
|
2020-08-07 14:17:48 +02:00
|
|
|
|
2021-06-16 20:09:45 +02:00
|
|
|
@DebugDump
|
2020-08-07 14:17:48 +02:00
|
|
|
public class PlayerSkinUpdater implements ServerEventListener {
|
|
|
|
|
2022-12-13 16:54:31 +01:00
|
|
|
private final Plugin plugin;
|
|
|
|
private final Map<UUID, Long> skinUpdates;
|
2021-09-19 22:15:50 +02:00
|
|
|
|
2022-12-13 16:54:31 +01:00
|
|
|
private SkinProvider skinProvider;
|
|
|
|
private PlayerIconFactory playerMarkerIconFactory;
|
2021-09-19 22:15:50 +02:00
|
|
|
|
2022-12-13 16:54:31 +01:00
|
|
|
public PlayerSkinUpdater(Plugin plugin) {
|
|
|
|
this.plugin = plugin;
|
|
|
|
this.skinUpdates = new ConcurrentHashMap<>();
|
2021-09-19 22:15:50 +02:00
|
|
|
|
2022-12-13 16:54:31 +01:00
|
|
|
skinProvider = new MojangSkinProvider();
|
|
|
|
playerMarkerIconFactory = new DefaultPlayerIconFactory();
|
2021-09-19 22:15:50 +02:00
|
|
|
}
|
|
|
|
|
2022-12-13 16:54:31 +01:00
|
|
|
public CompletableFuture<Void> updateSkin(final UUID playerUuid) {
|
|
|
|
|
|
|
|
// only update if last update was longer then an hour ago
|
|
|
|
long lastUpdate = skinUpdates.getOrDefault(playerUuid, 0L);
|
|
|
|
long now = System.currentTimeMillis();
|
|
|
|
if (now - lastUpdate < TimeUnit.HOURS.toMillis(1)) return CompletableFuture.completedFuture(null);
|
|
|
|
skinUpdates.put(playerUuid, now);
|
|
|
|
|
|
|
|
// do the update async
|
|
|
|
return CompletableFuture.supplyAsync(() -> {
|
|
|
|
try {
|
|
|
|
return skinProvider.load(playerUuid);
|
|
|
|
} catch (IOException e) {
|
|
|
|
throw new CompletionException("The skin provider threw an exception while loading the skin for UUID: '" + playerUuid + "'!", e);
|
|
|
|
}
|
|
|
|
}, BlueMap.THREAD_POOL).thenAcceptAsync(skin -> {
|
|
|
|
if (skin.isEmpty()) {
|
|
|
|
Logger.global.logDebug("No player-skin provided for UUID: " + playerUuid);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-02-01 23:01:42 +01:00
|
|
|
Map<String, BmMap> maps = plugin.getBlueMap().getMaps();
|
2022-12-13 16:54:31 +01:00
|
|
|
if (maps == null) {
|
|
|
|
Logger.global.logDebug("Could not update skin, since the plugin seems not to be ready.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
BufferedImage playerHead = playerMarkerIconFactory.apply(playerUuid, skin.get());
|
|
|
|
|
|
|
|
for (BmMap map : maps.values()) {
|
2022-12-29 17:54:17 +01:00
|
|
|
try (OutputStream out = map.getStorage().writeMeta(map.getId(), "assets/playerheads/" + playerUuid + ".png")) {
|
2022-12-13 16:54:31 +01:00
|
|
|
ImageIO.write(playerHead, "png", out);
|
|
|
|
} catch (IOException ex) {
|
|
|
|
Logger.global.logError("Failed to write player skin to storage: " + playerUuid, ex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}, BlueMap.THREAD_POOL);
|
2021-09-19 22:15:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onPlayerJoin(UUID playerUuid) {
|
2022-12-13 16:54:31 +01:00
|
|
|
updateSkin(playerUuid).exceptionally(ex -> {
|
|
|
|
Logger.global.logError("Failed to update player skin: " + playerUuid, ex);
|
|
|
|
return null;
|
|
|
|
});
|
2021-09-19 22:15:50 +02:00
|
|
|
}
|
|
|
|
|
2022-12-13 16:54:31 +01:00
|
|
|
public SkinProvider getSkinProvider() {
|
|
|
|
return skinProvider;
|
2021-09-19 22:15:50 +02:00
|
|
|
}
|
|
|
|
|
2022-12-13 16:54:31 +01:00
|
|
|
public void setSkinProvider(SkinProvider skinProvider) {
|
|
|
|
this.skinProvider = Objects.requireNonNull(skinProvider, "skinProvider can not be null");
|
2021-09-19 22:15:50 +02:00
|
|
|
}
|
|
|
|
|
2022-12-13 16:54:31 +01:00
|
|
|
public PlayerIconFactory getPlayerMarkerIconFactory() {
|
|
|
|
return playerMarkerIconFactory;
|
2021-09-19 22:15:50 +02:00
|
|
|
}
|
|
|
|
|
2022-12-13 16:54:31 +01:00
|
|
|
public void setPlayerMarkerIconFactory(PlayerIconFactory playerMarkerIconFactory) {
|
|
|
|
this.playerMarkerIconFactory = Objects.requireNonNull(playerMarkerIconFactory, "playerMarkerIconFactory can not be null");
|
2021-09-19 22:15:50 +02:00
|
|
|
}
|
2021-03-28 13:25:39 +02:00
|
|
|
|
2020-08-07 14:17:48 +02:00
|
|
|
}
|