Skip to content

Commit

Permalink
Add new skin fetcher
Browse files Browse the repository at this point in the history
  • Loading branch information
OliverSchlueter committed Nov 21, 2024
1 parent 5201ab6 commit 10a3de1
Show file tree
Hide file tree
Showing 4 changed files with 217 additions and 0 deletions.
24 changes: 24 additions & 0 deletions api/src/main/java/de/oliver/fancynpcs/api/skins/SkinData.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package de.oliver.fancynpcs.api.skins;

public record SkinData(
String identifier,
SkinType type,
SkinVariant variant,

String textureValue,
String textureSignature
) {

public enum SkinVariant {
SLIM,
DEFAULT
}

public enum SkinType {
USERNAME,
UUID,
URL,
FILE,
VALUE_SIGNATURE
}
}
17 changes: 17 additions & 0 deletions api/src/main/java/de/oliver/fancynpcs/api/skins/SkinFetcher.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package de.oliver.fancynpcs.api.skins;

import java.util.UUID;

public interface SkinFetcher {

SkinData getByUUID(UUID uuid);

SkinData getByUsername(String username);

SkinData getByURL(String url);

SkinData getByFile(String filePath);

SkinData get(String name, String value, String signature);

}
2 changes: 2 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ allprojects {
maven(url = "https://repo.papermc.io/repository/maven-public/")
maven(url = "https://repo.fancyplugins.de/releases")
maven(url = "https://repo.lushplugins.org/releases")
maven(url = "https://repo.inventivetalent.org/repository/public/")
}
}

Expand All @@ -67,6 +68,7 @@ dependencies {
implementation("org.incendo:cloud-paper:2.0.0-SNAPSHOT")
implementation("org.incendo:cloud-annotations:2.1.0-SNAPSHOT")
annotationProcessor("org.incendo:cloud-annotations:2.1.0-SNAPSHOT")
implementation("org.mineskin:java-client-jsoup:3.0.0-SNAPSHOT")

compileOnly("com.intellectualsites.plotsquared:plotsquared-core:7.4.0")
}
Expand Down
174 changes: 174 additions & 0 deletions src/main/java/de/oliver/fancynpcs/skins/SkinFetcherImpl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
package de.oliver.fancynpcs.skins;

import com.google.common.util.concurrent.ThreadFactoryBuilder;
import de.oliver.fancynpcs.FancyNpcs;
import de.oliver.fancynpcs.api.skins.SkinData;
import de.oliver.fancynpcs.api.skins.SkinFetcher;
import org.mineskin.JsoupRequestHandler;
import org.mineskin.MineSkinClient;
import org.mineskin.data.CodeAndMessage;
import org.mineskin.data.SkinInfo;
import org.mineskin.exception.MineSkinRequestException;
import org.mineskin.request.GenerateRequest;
import org.mineskin.response.JobResponse;
import org.mineskin.response.MineSkinResponse;
import org.mineskin.response.QueueResponse;

import java.io.File;
import java.net.MalformedURLException;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;

public class SkinFetcherImpl implements SkinFetcher {

private final ScheduledExecutorService executor;
private final MineSkinClient client;

public SkinFetcherImpl() {
this.executor = Executors.newSingleThreadScheduledExecutor(new ThreadFactoryBuilder()
.setNameFormat("FancyNpcs-Skins")
.build());

this.client = MineSkinClient.builder()
.requestHandler(JsoupRequestHandler::new)
.getExecutor(executor)
.generateExecutor(executor)
.generateRequestScheduler(executor)
.generateRequestScheduler(executor)
.jobCheckScheduler(executor)
.build();
}

@Override
public SkinData getByUUID(UUID uuid) {
GenerateRequest genReq = GenerateRequest.user(uuid);
SkinInfo skinInfo = executeRequest(genReq);

if (skinInfo == null) {
return null;
}

return new SkinData(
uuid.toString(),
SkinData.SkinType.UUID,
SkinData.SkinVariant.DEFAULT,
skinInfo.texture().data().value(),
skinInfo.texture().data().signature()
);
}

@Override
public SkinData getByUsername(String username) {
GenerateRequest genReq = GenerateRequest.user(username);
SkinInfo skinInfo = executeRequest(genReq);

if (skinInfo == null) {
return null;
}

return new SkinData(
username,
SkinData.SkinType.USERNAME,
SkinData.SkinVariant.DEFAULT,
skinInfo.texture().data().value(),
skinInfo.texture().data().signature()
);
}

@Override
public SkinData getByURL(String url) {
GenerateRequest genReq;
try {
genReq = GenerateRequest.url(url);
} catch (MalformedURLException e) {
FancyNpcs.getInstance().getFancyLogger().error("Invalid URL: " + url);
return null;
}

SkinInfo skinInfo = executeRequest(genReq);

if (skinInfo == null) {
return null;
}

return new SkinData(
url,
SkinData.SkinType.URL,
SkinData.SkinVariant.DEFAULT,
skinInfo.texture().data().value(),
skinInfo.texture().data().signature()
);
}

@Override
public SkinData getByFile(String filePath) {
File file = new File(filePath);
if (!file.exists()) {
FancyNpcs.getInstance().getFancyLogger().error("File does not exist: " + filePath);
return null;
}

GenerateRequest genReq = GenerateRequest.upload(file);
SkinInfo skinInfo = executeRequest(genReq);

if (skinInfo == null) {
return null;
}

return new SkinData(
filePath,
SkinData.SkinType.FILE,
SkinData.SkinVariant.DEFAULT,
skinInfo.texture().data().value(),
skinInfo.texture().data().signature()
);
}

@Override
public SkinData get(String name, String value, String signature) {
return new SkinData(
name,
SkinData.SkinType.VALUE_SIGNATURE,
SkinData.SkinVariant.DEFAULT,
value,
signature
);
}

private SkinInfo executeRequest(GenerateRequest req) {
// submit job to the queue
CompletableFuture<QueueResponse> queueResp = client.queue().submit(req);

// wait for job completion
CompletableFuture<JobResponse> jobResp = queueResp.thenCompose(
queueResponse -> queueResponse.getJob().waitForCompletion(client)
);

// get skin from job or load it from the API
CompletableFuture<SkinInfo> skinResp = jobResp.thenCompose(
jobResponse -> jobResponse.getOrLoadSkin(client)
);

// handle exceptions
skinResp.exceptionally(throwable -> {
if (throwable instanceof CompletionException completionException) {
throwable = completionException.getCause();
}

if (throwable instanceof MineSkinRequestException requestException) {
MineSkinResponse<?> response = requestException.getResponse();
Optional<CodeAndMessage> detailsOptional = response.getErrorOrMessage();
detailsOptional.ifPresent(details -> {
FancyNpcs.getInstance().getFancyLogger().warn("Could not fetch skin: " + details.code() + ": " + details.message());
});
}
return null;
});

return skinResp.join();
}
}

0 comments on commit 10a3de1

Please sign in to comment.