mirror of
https://github.com/Suiranoil/SkinRestorer.git
synced 2026-01-16 04:42:12 +00:00
implement Result type
This commit is contained in:
@@ -4,13 +4,13 @@ import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.properties.Property;
|
||||
import it.unimi.dsi.fastutil.Pair;
|
||||
import net.lionarius.skinrestorer.skin.SkinIO;
|
||||
import net.lionarius.skinrestorer.skin.SkinResult;
|
||||
import net.lionarius.skinrestorer.skin.SkinStorage;
|
||||
import net.lionarius.skinrestorer.skin.provider.MineskinSkinProvider;
|
||||
import net.lionarius.skinrestorer.skin.provider.MojangSkinProvider;
|
||||
import net.lionarius.skinrestorer.skin.provider.SkinProvider;
|
||||
import net.lionarius.skinrestorer.util.FileUtils;
|
||||
import net.lionarius.skinrestorer.util.PlayerUtils;
|
||||
import net.lionarius.skinrestorer.util.Result;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.level.storage.LevelResource;
|
||||
@@ -63,15 +63,19 @@ public final class SkinRestorer {
|
||||
SkinRestorer.skinStorage = new SkinStorage(new SkinIO(worldSkinDirectory));
|
||||
}
|
||||
|
||||
public static CompletableFuture<Pair<Collection<ServerPlayer>, Collection<GameProfile>>> setSkinAsync(MinecraftServer server, Collection<GameProfile> targets, Supplier<SkinResult> skinSupplier) {
|
||||
public static CompletableFuture<Pair<Collection<ServerPlayer>, Collection<GameProfile>>> setSkinAsync(
|
||||
MinecraftServer server,
|
||||
Collection<GameProfile> targets,
|
||||
Supplier<Result<Optional<Property>, ?>> skinSupplier
|
||||
) {
|
||||
return CompletableFuture.<Pair<Property, Collection<GameProfile>>>supplyAsync(() -> {
|
||||
SkinResult result = skinSupplier.get();
|
||||
var result = skinSupplier.get();
|
||||
if (result.isError()) {
|
||||
SkinRestorer.LOGGER.error("Could not get skin", result.getError());
|
||||
SkinRestorer.LOGGER.error("Could not get skin: {}", result.getErrorValue());
|
||||
return Pair.of(null, Collections.emptySet());
|
||||
}
|
||||
|
||||
Property skin = result.getSkin();
|
||||
Property skin = result.getSuccessValue().orElse(null);
|
||||
|
||||
for (GameProfile profile : targets) {
|
||||
SkinRestorer.getSkinStorage().setSkin(profile.getId(), skin);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package net.lionarius.skinrestorer.command;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.properties.Property;
|
||||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
import com.mojang.brigadier.builder.ArgumentBuilder;
|
||||
@@ -8,9 +9,9 @@ import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import net.lionarius.skinrestorer.SkinRestorer;
|
||||
import net.lionarius.skinrestorer.skin.SkinResult;
|
||||
import net.lionarius.skinrestorer.skin.SkinVariant;
|
||||
import net.lionarius.skinrestorer.skin.provider.SkinProvider;
|
||||
import net.lionarius.skinrestorer.util.Result;
|
||||
import net.lionarius.skinrestorer.util.TranslationUtils;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.arguments.GameProfileArgument;
|
||||
@@ -20,6 +21,7 @@ import net.minecraft.server.level.ServerPlayer;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@@ -33,7 +35,7 @@ public final class SkinCommand {
|
||||
public static void register(CommandDispatcher<CommandSourceStack> dispatcher) {
|
||||
LiteralArgumentBuilder<CommandSourceStack> base =
|
||||
literal("skin")
|
||||
.then(buildAction("clear", SkinResult::empty));
|
||||
.then(buildAction("clear", () -> Result.ofNullable(null)));
|
||||
|
||||
LiteralArgumentBuilder<CommandSourceStack> set = literal("set");
|
||||
|
||||
@@ -71,13 +73,16 @@ public final class SkinCommand {
|
||||
return action;
|
||||
}
|
||||
|
||||
private static ArgumentBuilder<CommandSourceStack, LiteralArgumentBuilder<CommandSourceStack>> buildAction(String name, Supplier<SkinResult> supplier) {
|
||||
private static ArgumentBuilder<CommandSourceStack, LiteralArgumentBuilder<CommandSourceStack>> buildAction(
|
||||
String name,
|
||||
Supplier<Result<Optional<Property>, ?>> supplier
|
||||
) {
|
||||
return buildArgument(literal(name), context -> supplier.get());
|
||||
}
|
||||
|
||||
private static <T extends ArgumentBuilder<CommandSourceStack, T>> ArgumentBuilder<CommandSourceStack, T> buildArgument(
|
||||
ArgumentBuilder<CommandSourceStack, T> argument,
|
||||
Function<CommandContext<CommandSourceStack>, SkinResult> provider
|
||||
Function<CommandContext<CommandSourceStack>, Result<Optional<Property>, ?>> provider
|
||||
) {
|
||||
return argument
|
||||
.executes(context -> skinAction(
|
||||
@@ -88,7 +93,7 @@ public final class SkinCommand {
|
||||
}
|
||||
|
||||
private static RequiredArgumentBuilder<CommandSourceStack, GameProfileArgument.Result> makeTargetsArgument(
|
||||
Function<CommandContext<CommandSourceStack>, SkinResult> provider
|
||||
Function<CommandContext<CommandSourceStack>, Result<Optional<Property>, ?>> provider
|
||||
) {
|
||||
return argument("targets", GameProfileArgument.gameProfile())
|
||||
.requires(source -> source.hasPermission(2))
|
||||
@@ -100,7 +105,12 @@ public final class SkinCommand {
|
||||
));
|
||||
}
|
||||
|
||||
private static int skinAction(CommandSourceStack src, Collection<GameProfile> targets, boolean setByOperator, Supplier<SkinResult> skinSupplier) {
|
||||
private static int skinAction(
|
||||
CommandSourceStack src,
|
||||
Collection<GameProfile> targets,
|
||||
boolean setByOperator,
|
||||
Supplier<Result<Optional<Property>, ?>> skinSupplier
|
||||
) {
|
||||
SkinRestorer.setSkinAsync(src.getServer(), targets, skinSupplier).thenAccept(pair -> {
|
||||
Collection<GameProfile> profiles = pair.right();
|
||||
Collection<ServerPlayer> players = pair.left();
|
||||
@@ -127,7 +137,7 @@ public final class SkinCommand {
|
||||
return targets.size();
|
||||
}
|
||||
|
||||
private static int skinAction(CommandSourceStack src, Supplier<SkinResult> skinSupplier) {
|
||||
private static int skinAction(CommandSourceStack src, Supplier<Result<Optional<Property>, ?>> skinSupplier) {
|
||||
if (src.getPlayer() == null)
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package net.lionarius.skinrestorer.mixin;
|
||||
|
||||
import net.lionarius.skinrestorer.SkinRestorer;
|
||||
import net.lionarius.skinrestorer.skin.SkinResult;
|
||||
import net.lionarius.skinrestorer.util.Result;
|
||||
import net.minecraft.network.Connection;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
@@ -40,6 +40,6 @@ public abstract class PlayerListMixin {
|
||||
|
||||
@Inject(method = "placeNewPlayer", at = @At("HEAD"))
|
||||
private void placeNewPlayer(Connection connection, ServerPlayer player, CommonListenerCookie cookie, CallbackInfo ci) {
|
||||
SkinRestorer.setSkinAsync(server, Collections.singleton(player.getGameProfile()), () -> SkinResult.ofNullable(SkinRestorer.getSkinStorage().getSkin(player.getUUID())));
|
||||
SkinRestorer.setSkinAsync(server, Collections.singleton(player.getGameProfile()), () -> Result.ofNullable(SkinRestorer.getSkinStorage().getSkin(player.getUUID())));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@ package net.lionarius.skinrestorer.mixin;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import net.lionarius.skinrestorer.SkinRestorer;
|
||||
import net.lionarius.skinrestorer.skin.SkinResult;
|
||||
import net.lionarius.skinrestorer.skin.SkinVariant;
|
||||
import net.lionarius.skinrestorer.util.Result;
|
||||
import net.minecraft.server.network.ServerLoginPacketListenerImpl;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
@@ -22,7 +22,7 @@ public abstract class ServerLoginPacketListenerImplMixin {
|
||||
private GameProfile authenticatedProfile;
|
||||
|
||||
@Unique
|
||||
private CompletableFuture<SkinResult> skinrestorer_pendingSkin;
|
||||
private CompletableFuture<Void> skinrestorer_pendingSkin;
|
||||
|
||||
@Inject(method = "verifyLoginAndFinishConnectionSetup", at = @At(value = "INVOKE",
|
||||
target = "Lnet/minecraft/server/players/PlayerList;canPlayerLogin(Ljava/net/SocketAddress;Lcom/mojang/authlib/GameProfile;)Lnet/minecraft/network/chat/Component;"),
|
||||
@@ -34,15 +34,17 @@ public abstract class ServerLoginPacketListenerImplMixin {
|
||||
SkinRestorer.LOGGER.debug("Fetching {}'s skin", authenticatedProfile.getName());
|
||||
|
||||
if (!SkinRestorer.getSkinStorage().hasSavedSkin(authenticatedProfile.getId())) { // when player joins for the first time fetch Mojang skin by his username
|
||||
SkinResult result = SkinRestorer.getProvider("mojang").map(
|
||||
var result = SkinRestorer.getProvider("mojang").map(
|
||||
provider -> provider.getSkin(authenticatedProfile.getName(), SkinVariant.CLASSIC)
|
||||
).orElse(SkinResult.empty());
|
||||
).orElse(Result.ofNullable(null));
|
||||
|
||||
if (!result.isError())
|
||||
SkinRestorer.getSkinStorage().setSkin(authenticatedProfile.getId(), result.getSkin());
|
||||
SkinRestorer.getSkinStorage().setSkin(authenticatedProfile.getId(), result.getSuccessValue().orElse(null));
|
||||
}
|
||||
|
||||
return SkinResult.ofNullable(SkinRestorer.getSkinStorage().getSkin(authenticatedProfile.getId()));
|
||||
SkinRestorer.getSkinStorage().getSkin(authenticatedProfile.getId()); // loads skin from disk
|
||||
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
package net.lionarius.skinrestorer.skin;
|
||||
|
||||
import com.mojang.authlib.properties.Property;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class SkinResult {
|
||||
private final Property skin;
|
||||
private final Exception exception;
|
||||
|
||||
private SkinResult(Property skin, Exception exception) {
|
||||
this.skin = skin;
|
||||
this.exception = exception;
|
||||
}
|
||||
|
||||
public Property getSkin() {
|
||||
return this.skin;
|
||||
}
|
||||
|
||||
public Exception getError() {
|
||||
return this.exception;
|
||||
}
|
||||
|
||||
public boolean isError() {
|
||||
return this.exception != null;
|
||||
}
|
||||
|
||||
public static SkinResult empty() {
|
||||
return new SkinResult(null, null);
|
||||
}
|
||||
|
||||
public static SkinResult error(Exception e) {
|
||||
return new SkinResult(null, e);
|
||||
}
|
||||
|
||||
public static SkinResult success(@NotNull Property skin) {
|
||||
return new SkinResult(skin, null);
|
||||
}
|
||||
|
||||
public static SkinResult ofNullable(Property skin) {
|
||||
if (skin == null)
|
||||
return SkinResult.empty();
|
||||
|
||||
return SkinResult.success(skin);
|
||||
}
|
||||
}
|
||||
@@ -2,15 +2,16 @@ package net.lionarius.skinrestorer.skin.provider;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.mojang.authlib.properties.Property;
|
||||
import net.lionarius.skinrestorer.skin.SkinResult;
|
||||
import com.mojang.datafixers.util.Either;
|
||||
import net.lionarius.skinrestorer.skin.SkinVariant;
|
||||
import net.lionarius.skinrestorer.util.JsonUtils;
|
||||
import net.lionarius.skinrestorer.util.PlayerUtils;
|
||||
import net.lionarius.skinrestorer.util.Result;
|
||||
import net.lionarius.skinrestorer.util.WebUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Optional;
|
||||
|
||||
public final class MineskinSkinProvider implements SkinProvider {
|
||||
|
||||
@@ -35,7 +36,7 @@ public final class MineskinSkinProvider implements SkinProvider {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SkinResult getSkin(String url, SkinVariant variant) {
|
||||
public Result<Optional<Property>, Exception> getSkin(String url, SkinVariant variant) {
|
||||
try {
|
||||
String body = ("{\"variant\":\"%s\",\"name\":\"%s\",\"visibility\":%d,\"url\":\"%s\"}")
|
||||
.formatted(variant.toString(), "none", 1, url);
|
||||
@@ -43,9 +44,9 @@ public final class MineskinSkinProvider implements SkinProvider {
|
||||
JsonObject texture = JsonUtils.parseJson(WebUtils.postRequest(API_URL.toURL(), "application/json", body))
|
||||
.getAsJsonObject("data").getAsJsonObject("texture");
|
||||
|
||||
return SkinResult.success(new Property(PlayerUtils.TEXTURES_KEY, texture.get("value").getAsString(), texture.get("signature").getAsString()));
|
||||
} catch (IOException e) {
|
||||
return SkinResult.error(e);
|
||||
return Result.ofNullable(new Property(PlayerUtils.TEXTURES_KEY, texture.get("value").getAsString(), texture.get("signature").getAsString()));
|
||||
} catch (Exception e) {
|
||||
return Result.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,15 +2,16 @@ package net.lionarius.skinrestorer.skin.provider;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.mojang.authlib.properties.Property;
|
||||
import net.lionarius.skinrestorer.skin.SkinResult;
|
||||
import net.lionarius.skinrestorer.skin.SkinVariant;
|
||||
import net.lionarius.skinrestorer.util.JsonUtils;
|
||||
import net.lionarius.skinrestorer.util.PlayerUtils;
|
||||
import net.lionarius.skinrestorer.util.Result;
|
||||
import net.lionarius.skinrestorer.util.WebUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public final class MojangSkinProvider implements SkinProvider {
|
||||
@@ -39,15 +40,15 @@ public final class MojangSkinProvider implements SkinProvider {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SkinResult getSkin(String username, SkinVariant variant) {
|
||||
public Result<Optional<Property>, Exception> getSkin(String username, SkinVariant variant) {
|
||||
try {
|
||||
UUID uuid = getUUID(username);
|
||||
JsonObject texture = JsonUtils.parseJson(WebUtils.getRequest(SESSION_SERVER_URL.resolve(uuid + "?unsigned=false").toURL()))
|
||||
.getAsJsonArray("properties").get(0).getAsJsonObject();
|
||||
|
||||
return SkinResult.success(new Property(PlayerUtils.TEXTURES_KEY, texture.get("value").getAsString(), texture.get("signature").getAsString()));
|
||||
return Result.ofNullable(new Property(PlayerUtils.TEXTURES_KEY, texture.get("value").getAsString(), texture.get("signature").getAsString()));
|
||||
} catch (Exception e) {
|
||||
return SkinResult.error(e);
|
||||
return Result.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
package net.lionarius.skinrestorer.skin.provider;
|
||||
|
||||
import net.lionarius.skinrestorer.skin.SkinResult;
|
||||
import com.mojang.authlib.properties.Property;
|
||||
import net.lionarius.skinrestorer.skin.SkinVariant;
|
||||
import net.lionarius.skinrestorer.util.Result;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public interface SkinProvider {
|
||||
|
||||
@@ -9,5 +12,5 @@ public interface SkinProvider {
|
||||
|
||||
boolean hasVariantSupport();
|
||||
|
||||
SkinResult getSkin(String argument, SkinVariant variant);
|
||||
Result<Optional<Property>, Exception> getSkin(String argument, SkinVariant variant);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
package net.lionarius.skinrestorer.util;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class Result<S, E> {
|
||||
|
||||
private final S successValue;
|
||||
private final E errorValue;
|
||||
|
||||
private Result(S successValue, E errorValue) {
|
||||
if (successValue == null && errorValue == null)
|
||||
throw new IllegalArgumentException("Cannot create result of null values");
|
||||
|
||||
this.successValue = successValue;
|
||||
this.errorValue = errorValue;
|
||||
}
|
||||
|
||||
public S getSuccessValue() {
|
||||
return successValue;
|
||||
}
|
||||
|
||||
public E getErrorValue() {
|
||||
return errorValue;
|
||||
}
|
||||
|
||||
public boolean isSuccess() {
|
||||
return successValue != null;
|
||||
}
|
||||
|
||||
public boolean isError() {
|
||||
return errorValue != null;
|
||||
}
|
||||
|
||||
public <N> Result<N, E> map(Function<S, N> mapper) {
|
||||
if (successValue == null)
|
||||
return new Result<>(null, errorValue);
|
||||
|
||||
return new Result<>(mapper.apply(successValue), errorValue);
|
||||
}
|
||||
|
||||
public <N> Result<S, N> mapError(Function<E, N> mapper) {
|
||||
if (errorValue == null)
|
||||
return new Result<>(successValue, null);
|
||||
|
||||
return new Result<>(successValue, mapper.apply(errorValue));
|
||||
}
|
||||
|
||||
public Optional<S> toOptional() {
|
||||
return Optional.ofNullable(successValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o)
|
||||
return true;
|
||||
|
||||
if (o == null || getClass() != o.getClass())
|
||||
return false;
|
||||
|
||||
Result<?, ?> result = (Result<?, ?>) o;
|
||||
return Objects.equals(successValue, result.successValue) && Objects.equals(errorValue, result.errorValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(successValue, errorValue);
|
||||
}
|
||||
|
||||
public static <S, E> Result<S, E> success(@NotNull S successValue) {
|
||||
return new Result<>(successValue, null);
|
||||
}
|
||||
|
||||
public static <S, E> Result<S, E> error(@NotNull E errorValue) {
|
||||
return new Result<>(null, errorValue);
|
||||
}
|
||||
|
||||
public static <S, E> Result<Optional<S>, E> ofNullable(S successValue) {
|
||||
return Result.success(Optional.ofNullable(successValue));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user