From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: violetc <58360096+s-yh-china@users.noreply.github.com> Date: Thu, 2 Feb 2023 16:01:18 +0800 Subject: [PATCH] Leaves Extra Yggdrasil Service diff --git a/src/main/java/com/destroystokyo/paper/profile/PaperAuthenticationService.java b/src/main/java/com/destroystokyo/paper/profile/PaperAuthenticationService.java index 48e774677edf17d4a99ae9ed23d1b371dab41abb..21409ff86db65c00d92bff9eae8bdeb3a872a361 100644 --- a/src/main/java/com/destroystokyo/paper/profile/PaperAuthenticationService.java +++ b/src/main/java/com/destroystokyo/paper/profile/PaperAuthenticationService.java @@ -11,7 +11,7 @@ import java.net.Proxy; public class PaperAuthenticationService extends YggdrasilAuthenticationService { - private final Environment environment; + protected final Environment environment; // Leaves - private -> protected public PaperAuthenticationService(Proxy proxy) { super(proxy); diff --git a/src/main/java/com/mojang/authlib/yggdrasil/YggdrasilMinecraftSessionService.java b/src/main/java/com/mojang/authlib/yggdrasil/YggdrasilMinecraftSessionService.java index bfc1e27c37689c1fbb927404a7176780a439a057..bc8ab50ef1390a2c51110a89dc43db58215396a9 100644 --- a/src/main/java/com/mojang/authlib/yggdrasil/YggdrasilMinecraftSessionService.java +++ b/src/main/java/com/mojang/authlib/yggdrasil/YggdrasilMinecraftSessionService.java @@ -46,7 +46,7 @@ import java.util.stream.Collectors; public class YggdrasilMinecraftSessionService implements MinecraftSessionService { private static final Logger LOGGER = LoggerFactory.getLogger(YggdrasilMinecraftSessionService.class); - private final MinecraftClient client; + protected final MinecraftClient client; // Leaves - private -> protected private final ServicesKeySet servicesKeySet; private final String baseUrl; private final URL joinUrl; diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java index 581bd217304e0f9e0b2113c335694805dfb4e2a1..be579118fe33215016b25b144b405d10c7a36fbf 100644 --- a/src/main/java/net/minecraft/server/Main.java +++ b/src/main/java/net/minecraft/server/Main.java @@ -191,7 +191,7 @@ public class Main { file = new File(bukkitConfiguration.getString("settings.world-container", ".")); } // Paper end - fix SPIGOT-5824 - Services services = Services.create(new com.destroystokyo.paper.profile.PaperAuthenticationService(Proxy.NO_PROXY), file, userCacheFile, optionset); // Paper - pass OptionSet to load paper config files; override authentication service; fix world-container + Services services = Services.create(new org.leavesmc.leaves.profile.LeavesAuthenticationService(Proxy.NO_PROXY), file, userCacheFile, optionset); // Paper - pass OptionSet to load paper config files; override authentication service; fix world-container // Leaves - extra-yggdrasil-service // CraftBukkit start String s = (String) Optional.ofNullable((String) optionset.valueOf("world")).orElse(dedicatedserversettings.getProperties().levelName); LevelStorageSource convertable = LevelStorageSource.createDefault(file.toPath()); diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java index 0f07ee9d947235fc91f7d450d746f056a9b9e13a..375f4c7fc502902df9defd37409c4b54e643acfe 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -265,7 +265,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop public private long lastServerStatus; public final Thread serverThread; private long lastTickNanos; diff --git a/src/main/java/org/leavesmc/leaves/profile/LeavesAuthenticationService.java b/src/main/java/org/leavesmc/leaves/profile/LeavesAuthenticationService.java new file mode 100644 index 0000000000000000000000000000000000000000..6f14a66d78709fae9fecbefc80e3489b68e8d0c7 --- /dev/null +++ b/src/main/java/org/leavesmc/leaves/profile/LeavesAuthenticationService.java @@ -0,0 +1,18 @@ +package org.leavesmc.leaves.profile; + +import com.destroystokyo.paper.profile.PaperAuthenticationService; +import com.mojang.authlib.minecraft.MinecraftSessionService; + +import java.net.Proxy; + +public class LeavesAuthenticationService extends PaperAuthenticationService { + + public LeavesAuthenticationService(Proxy proxy) { + super(proxy); + } + + @Override + public MinecraftSessionService createMinecraftSessionService() { + return new LeavesMinecraftSessionService(this.getServicesKeySet(), this.getProxy(), this.environment); + } +} diff --git a/src/main/java/org/leavesmc/leaves/profile/LeavesMinecraftSessionService.java b/src/main/java/org/leavesmc/leaves/profile/LeavesMinecraftSessionService.java new file mode 100644 index 0000000000000000000000000000000000000000..b15ee80ac1aea751594cd3321928f26d3cbf243e --- /dev/null +++ b/src/main/java/org/leavesmc/leaves/profile/LeavesMinecraftSessionService.java @@ -0,0 +1,102 @@ +package org.leavesmc.leaves.profile; + +import com.destroystokyo.paper.profile.PaperMinecraftSessionService; +import com.mojang.authlib.Environment; +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.HttpAuthenticationService; +import com.mojang.authlib.exceptions.AuthenticationUnavailableException; +import com.mojang.authlib.exceptions.MinecraftClientException; +import com.mojang.authlib.yggdrasil.ProfileActionType; +import com.mojang.authlib.yggdrasil.ProfileResult; +import com.mojang.authlib.yggdrasil.ServicesKeySet; +import com.mojang.authlib.yggdrasil.response.HasJoinedMinecraftServerResponse; +import com.mojang.authlib.yggdrasil.response.ProfileAction; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerPlayer; +import org.jetbrains.annotations.Nullable; +import org.leavesmc.leaves.LeavesConfig; +import org.leavesmc.leaves.bot.ServerBot; + +import java.net.InetAddress; +import java.net.Proxy; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +public class LeavesMinecraftSessionService extends PaperMinecraftSessionService { + + protected LeavesMinecraftSessionService(ServicesKeySet keySet, Proxy authenticationService, Environment environment) { + super(keySet, authenticationService, environment); + } + + private static List extraYggdrasilList = List.of(); + + public static void initExtraYggdrasilList(List extraYggdrasilServiceList) { + List list = new ArrayList<>(); + for (String str : extraYggdrasilServiceList) { + list.add(HttpAuthenticationService.constantURL(str + "/sessionserver/session/minecraft/hasJoined")); + } + extraYggdrasilList = Collections.unmodifiableList(list); + } + + @Nullable + @Override + public ProfileResult hasJoinedServer(String profileName, String serverId, @Nullable InetAddress address) throws AuthenticationUnavailableException { + ProfileResult result = super.hasJoinedServer(profileName, serverId, address); // mojang + + ServerPlayer player = MinecraftServer.getServer().getPlayerList().getPlayerByName(profileName); + if (player != null && !(player instanceof ServerBot)) { + return null; // if it has same name, return null + } + + if (LeavesConfig.extraYggdrasilService && result == null) { + final Map arguments = new HashMap<>(); + arguments.put("username", profileName); + arguments.put("serverId", serverId); + + if (address != null) { + arguments.put("ip", address.getHostAddress()); + } + + GameProfile cache = null; + if (LeavesConfig.extraYggdrasilLoginProtect) { + cache = MinecraftServer.getServer().services.profileCache().getProfileIfCached(profileName); + } + + for (URL checkUrl : extraYggdrasilList) { + URL url = HttpAuthenticationService.concatenateURL(checkUrl, HttpAuthenticationService.buildQuery(arguments)); + try { + final HasJoinedMinecraftServerResponse response = client.get(url, HasJoinedMinecraftServerResponse.class); + if (response != null && response.id() != null) { + if (LeavesConfig.extraYggdrasilLoginProtect && cache != null) { + if (response.id() != cache.getId()) { + continue; + } + } + + final GameProfile result1 = new GameProfile(response.id(), profileName); + + if (response.properties() != null) { + result1.getProperties().putAll(response.properties()); + } + + final Set profileActions = response.profileActions().stream() + .map(ProfileAction::type) + .collect(Collectors.toSet()); + return new ProfileResult(result1, profileActions); + } + } catch (final MinecraftClientException e) { + if (e.toAuthenticationException() instanceof final AuthenticationUnavailableException unavailable) { + throw unavailable; + } + } + } + } + return result; + } +}