2025-11-24 22:52:51 +03:00

466 lines
21 KiB
Java

/*
* Decompiled with CFR 0.152.
*
* Could not load the following classes:
* com.google.common.collect.Lists
* com.google.common.collect.Maps
* com.google.common.io.Files
* com.mojang.authlib.ProfileLookupCallback
* com.mojang.authlib.yggdrasil.ProfileNotFoundException
* com.mojang.logging.LogUtils
* org.jspecify.annotations.Nullable
* org.slf4j.Logger
*/
package net.minecraft.server.players;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.io.Files;
import com.mojang.authlib.ProfileLookupCallback;
import com.mojang.authlib.yggdrasil.ProfileNotFoundException;
import com.mojang.logging.LogUtils;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import net.minecraft.core.UUIDUtil;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.dedicated.DedicatedServer;
import net.minecraft.server.notifications.EmptyNotificationService;
import net.minecraft.server.players.BanListEntry;
import net.minecraft.server.players.IpBanList;
import net.minecraft.server.players.IpBanListEntry;
import net.minecraft.server.players.NameAndId;
import net.minecraft.server.players.PlayerList;
import net.minecraft.server.players.ServerOpList;
import net.minecraft.server.players.ServerOpListEntry;
import net.minecraft.server.players.UserBanList;
import net.minecraft.server.players.UserBanListEntry;
import net.minecraft.server.players.UserWhiteList;
import net.minecraft.server.players.UserWhiteListEntry;
import net.minecraft.util.StringUtil;
import net.minecraft.world.level.storage.LevelResource;
import org.jspecify.annotations.Nullable;
import org.slf4j.Logger;
public class OldUsersConverter {
private static final Logger LOGGER = LogUtils.getLogger();
public static final File OLD_IPBANLIST = new File("banned-ips.txt");
public static final File OLD_USERBANLIST = new File("banned-players.txt");
public static final File OLD_OPLIST = new File("ops.txt");
public static final File OLD_WHITELIST = new File("white-list.txt");
static List<String> readOldListFormat(File file, Map<String, String[]> userMap) throws IOException {
List lines = Files.readLines((File)file, (Charset)StandardCharsets.UTF_8);
for (String line : lines) {
if ((line = line.trim()).startsWith("#") || line.length() < 1) continue;
String[] parts = line.split("\\|");
userMap.put(parts[0].toLowerCase(Locale.ROOT), parts);
}
return lines;
}
private static void lookupPlayers(MinecraftServer server, Collection<String> names, ProfileLookupCallback callback) {
String[] filteredNames = (String[])names.stream().filter(s -> !StringUtil.isNullOrEmpty(s)).toArray(String[]::new);
if (server.usesAuthentication()) {
server.services().profileRepository().findProfilesByNames(filteredNames, callback);
} else {
for (String name : filteredNames) {
callback.onProfileLookupSucceeded(name, UUIDUtil.createOfflinePlayerUUID(name));
}
}
}
public static boolean convertUserBanlist(final MinecraftServer server) {
final UserBanList bans = new UserBanList(PlayerList.USERBANLIST_FILE, new EmptyNotificationService());
if (OLD_USERBANLIST.exists() && OLD_USERBANLIST.isFile()) {
if (bans.getFile().exists()) {
try {
bans.load();
}
catch (IOException e) {
LOGGER.warn("Could not load existing file {}", (Object)bans.getFile().getName(), (Object)e);
}
}
try {
final HashMap userMap = Maps.newHashMap();
OldUsersConverter.readOldListFormat(OLD_USERBANLIST, userMap);
ProfileLookupCallback callback = new ProfileLookupCallback(){
public void onProfileLookupSucceeded(String profileName, UUID profileId) {
NameAndId profile = new NameAndId(profileId, profileName);
server.services().nameToIdCache().add(profile);
String[] userDef = (String[])userMap.get(profile.name().toLowerCase(Locale.ROOT));
if (userDef == null) {
LOGGER.warn("Could not convert user banlist entry for {}", (Object)profile.name());
throw new ConversionError("Profile not in the conversionlist");
}
Date created = userDef.length > 1 ? OldUsersConverter.parseDate(userDef[1], null) : null;
String source = userDef.length > 2 ? userDef[2] : null;
Date expires = userDef.length > 3 ? OldUsersConverter.parseDate(userDef[3], null) : null;
String reason = userDef.length > 4 ? userDef[4] : null;
bans.add(new UserBanListEntry(profile, created, source, expires, reason));
}
public void onProfileLookupFailed(String profileName, Exception exception) {
LOGGER.warn("Could not lookup user banlist entry for {}", (Object)profileName, (Object)exception);
if (!(exception instanceof ProfileNotFoundException)) {
throw new ConversionError("Could not request user " + profileName + " from backend systems", exception);
}
}
};
OldUsersConverter.lookupPlayers(server, userMap.keySet(), callback);
bans.save();
OldUsersConverter.renameOldFile(OLD_USERBANLIST);
}
catch (IOException e) {
LOGGER.warn("Could not read old user banlist to convert it!", (Throwable)e);
return false;
}
catch (ConversionError e) {
LOGGER.error("Conversion failed, please try again later", (Throwable)e);
return false;
}
return true;
}
return true;
}
public static boolean convertIpBanlist(MinecraftServer server) {
IpBanList ipBans = new IpBanList(PlayerList.IPBANLIST_FILE, new EmptyNotificationService());
if (OLD_IPBANLIST.exists() && OLD_IPBANLIST.isFile()) {
if (ipBans.getFile().exists()) {
try {
ipBans.load();
}
catch (IOException e) {
LOGGER.warn("Could not load existing file {}", (Object)ipBans.getFile().getName(), (Object)e);
}
}
try {
HashMap userMap = Maps.newHashMap();
OldUsersConverter.readOldListFormat(OLD_IPBANLIST, userMap);
for (String key : userMap.keySet()) {
String[] userDef = (String[])userMap.get(key);
Date created = userDef.length > 1 ? OldUsersConverter.parseDate(userDef[1], null) : null;
String source = userDef.length > 2 ? userDef[2] : null;
Date expires = userDef.length > 3 ? OldUsersConverter.parseDate(userDef[3], null) : null;
String reason = userDef.length > 4 ? userDef[4] : null;
ipBans.add(new IpBanListEntry(key, created, source, expires, reason));
}
ipBans.save();
OldUsersConverter.renameOldFile(OLD_IPBANLIST);
}
catch (IOException e) {
LOGGER.warn("Could not parse old ip banlist to convert it!", (Throwable)e);
return false;
}
return true;
}
return true;
}
public static boolean convertOpsList(final MinecraftServer server) {
final ServerOpList opsList = new ServerOpList(PlayerList.OPLIST_FILE, new EmptyNotificationService());
if (OLD_OPLIST.exists() && OLD_OPLIST.isFile()) {
if (opsList.getFile().exists()) {
try {
opsList.load();
}
catch (IOException e) {
LOGGER.warn("Could not load existing file {}", (Object)opsList.getFile().getName(), (Object)e);
}
}
try {
List lines = Files.readLines((File)OLD_OPLIST, (Charset)StandardCharsets.UTF_8);
ProfileLookupCallback callback = new ProfileLookupCallback(){
public void onProfileLookupSucceeded(String profileName, UUID profileId) {
NameAndId profile = new NameAndId(profileId, profileName);
server.services().nameToIdCache().add(profile);
opsList.add(new ServerOpListEntry(profile, server.operatorUserPermissions(), false));
}
public void onProfileLookupFailed(String profileName, Exception exception) {
LOGGER.warn("Could not lookup oplist entry for {}", (Object)profileName, (Object)exception);
if (!(exception instanceof ProfileNotFoundException)) {
throw new ConversionError("Could not request user " + profileName + " from backend systems", exception);
}
}
};
OldUsersConverter.lookupPlayers(server, lines, callback);
opsList.save();
OldUsersConverter.renameOldFile(OLD_OPLIST);
}
catch (IOException e) {
LOGGER.warn("Could not read old oplist to convert it!", (Throwable)e);
return false;
}
catch (ConversionError e) {
LOGGER.error("Conversion failed, please try again later", (Throwable)e);
return false;
}
return true;
}
return true;
}
public static boolean convertWhiteList(final MinecraftServer server) {
final UserWhiteList whitelist = new UserWhiteList(PlayerList.WHITELIST_FILE, new EmptyNotificationService());
if (OLD_WHITELIST.exists() && OLD_WHITELIST.isFile()) {
if (whitelist.getFile().exists()) {
try {
whitelist.load();
}
catch (IOException e) {
LOGGER.warn("Could not load existing file {}", (Object)whitelist.getFile().getName(), (Object)e);
}
}
try {
List lines = Files.readLines((File)OLD_WHITELIST, (Charset)StandardCharsets.UTF_8);
ProfileLookupCallback callback = new ProfileLookupCallback(){
public void onProfileLookupSucceeded(String profileName, UUID profileId) {
NameAndId profile = new NameAndId(profileId, profileName);
server.services().nameToIdCache().add(profile);
whitelist.add(new UserWhiteListEntry(profile));
}
public void onProfileLookupFailed(String profileName, Exception exception) {
LOGGER.warn("Could not lookup user whitelist entry for {}", (Object)profileName, (Object)exception);
if (!(exception instanceof ProfileNotFoundException)) {
throw new ConversionError("Could not request user " + profileName + " from backend systems", exception);
}
}
};
OldUsersConverter.lookupPlayers(server, lines, callback);
whitelist.save();
OldUsersConverter.renameOldFile(OLD_WHITELIST);
}
catch (IOException e) {
LOGGER.warn("Could not read old whitelist to convert it!", (Throwable)e);
return false;
}
catch (ConversionError e) {
LOGGER.error("Conversion failed, please try again later", (Throwable)e);
return false;
}
return true;
}
return true;
}
public static @Nullable UUID convertMobOwnerIfNecessary(final MinecraftServer server, String owner) {
if (StringUtil.isNullOrEmpty(owner) || owner.length() > 16) {
try {
return UUID.fromString(owner);
}
catch (IllegalArgumentException ignored) {
return null;
}
}
Optional<UUID> profileId = server.services().nameToIdCache().get(owner).map(NameAndId::id);
if (profileId.isPresent()) {
return profileId.get();
}
if (server.isSingleplayer() || !server.usesAuthentication()) {
return UUIDUtil.createOfflinePlayerUUID(owner);
}
final ArrayList profiles = new ArrayList();
ProfileLookupCallback callback = new ProfileLookupCallback(){
public void onProfileLookupSucceeded(String profileName, UUID profileId) {
NameAndId profile = new NameAndId(profileId, profileName);
server.services().nameToIdCache().add(profile);
profiles.add(profile);
}
public void onProfileLookupFailed(String profileName, Exception exception) {
LOGGER.warn("Could not lookup user whitelist entry for {}", (Object)profileName, (Object)exception);
}
};
OldUsersConverter.lookupPlayers(server, Lists.newArrayList((Object[])new String[]{owner}), callback);
if (!profiles.isEmpty()) {
return ((NameAndId)profiles.getFirst()).id();
}
return null;
}
public static boolean convertPlayers(final DedicatedServer server) {
final File worldPlayerDirectory = OldUsersConverter.getWorldPlayersDirectory(server);
final File worldNewPlayerDirectory = new File(worldPlayerDirectory.getParentFile(), "playerdata");
final File unknownPlayerDirectory = new File(worldPlayerDirectory.getParentFile(), "unknownplayers");
if (!worldPlayerDirectory.exists() || !worldPlayerDirectory.isDirectory()) {
return true;
}
File[] playerFiles = worldPlayerDirectory.listFiles();
ArrayList playerNames = Lists.newArrayList();
for (File file : playerFiles) {
String playerName;
String fileName = file.getName();
if (!fileName.toLowerCase(Locale.ROOT).endsWith(".dat") || (playerName = fileName.substring(0, fileName.length() - ".dat".length())).isEmpty()) continue;
playerNames.add(playerName);
}
try {
Object[] names = playerNames.toArray(new String[playerNames.size()]);
ProfileLookupCallback callback = new ProfileLookupCallback(){
final /* synthetic */ String[] val$names;
{
this.val$names = stringArray;
}
public void onProfileLookupSucceeded(String profileName, UUID profileId) {
NameAndId profile = new NameAndId(profileId, profileName);
server.services().nameToIdCache().add(profile);
this.movePlayerFile(worldNewPlayerDirectory, this.getFileNameForProfile(profileName), profileId.toString());
}
public void onProfileLookupFailed(String profileName, Exception exception) {
LOGGER.warn("Could not lookup user uuid for {}", (Object)profileName, (Object)exception);
if (!(exception instanceof ProfileNotFoundException)) {
throw new ConversionError("Could not request user " + profileName + " from backend systems", exception);
}
String fileNameForProfile = this.getFileNameForProfile(profileName);
this.movePlayerFile(unknownPlayerDirectory, fileNameForProfile, fileNameForProfile);
}
private void movePlayerFile(File directory, String oldName, String newName) {
File oldFileName = new File(worldPlayerDirectory, oldName + ".dat");
File newFileName = new File(directory, newName + ".dat");
OldUsersConverter.ensureDirectoryExists(directory);
if (!oldFileName.renameTo(newFileName)) {
throw new ConversionError("Could not convert file for " + oldName);
}
}
private String getFileNameForProfile(String profileName) {
String fileName = null;
for (String name : this.val$names) {
if (name == null || !name.equalsIgnoreCase(profileName)) continue;
fileName = name;
break;
}
if (fileName == null) {
throw new ConversionError("Could not find the filename for " + profileName + " anymore");
}
return fileName;
}
};
OldUsersConverter.lookupPlayers(server, Lists.newArrayList((Object[])names), callback);
}
catch (ConversionError e) {
LOGGER.error("Conversion failed, please try again later", (Throwable)e);
return false;
}
return true;
}
private static void ensureDirectoryExists(File directory) {
if (directory.exists()) {
if (directory.isDirectory()) {
return;
}
throw new ConversionError("Can't create directory " + directory.getName() + " in world save directory.");
}
if (!directory.mkdirs()) {
throw new ConversionError("Can't create directory " + directory.getName() + " in world save directory.");
}
}
public static boolean serverReadyAfterUserconversion(MinecraftServer server) {
boolean ready = OldUsersConverter.areOldUserlistsRemoved();
ready = ready && OldUsersConverter.areOldPlayersConverted(server);
return ready;
}
private static boolean areOldUserlistsRemoved() {
boolean foundUserBanlist = false;
if (OLD_USERBANLIST.exists() && OLD_USERBANLIST.isFile()) {
foundUserBanlist = true;
}
boolean foundIpBanlist = false;
if (OLD_IPBANLIST.exists() && OLD_IPBANLIST.isFile()) {
foundIpBanlist = true;
}
boolean foundOpList = false;
if (OLD_OPLIST.exists() && OLD_OPLIST.isFile()) {
foundOpList = true;
}
boolean foundWhitelist = false;
if (OLD_WHITELIST.exists() && OLD_WHITELIST.isFile()) {
foundWhitelist = true;
}
if (foundUserBanlist || foundIpBanlist || foundOpList || foundWhitelist) {
LOGGER.warn("**** FAILED TO START THE SERVER AFTER ACCOUNT CONVERSION!");
LOGGER.warn("** please remove the following files and restart the server:");
if (foundUserBanlist) {
LOGGER.warn("* {}", (Object)OLD_USERBANLIST.getName());
}
if (foundIpBanlist) {
LOGGER.warn("* {}", (Object)OLD_IPBANLIST.getName());
}
if (foundOpList) {
LOGGER.warn("* {}", (Object)OLD_OPLIST.getName());
}
if (foundWhitelist) {
LOGGER.warn("* {}", (Object)OLD_WHITELIST.getName());
}
return false;
}
return true;
}
private static boolean areOldPlayersConverted(MinecraftServer server) {
File worldPlayerDirectory = OldUsersConverter.getWorldPlayersDirectory(server);
if (worldPlayerDirectory.exists() && worldPlayerDirectory.isDirectory() && (worldPlayerDirectory.list().length > 0 || !worldPlayerDirectory.delete())) {
LOGGER.warn("**** DETECTED OLD PLAYER DIRECTORY IN THE WORLD SAVE");
LOGGER.warn("**** THIS USUALLY HAPPENS WHEN THE AUTOMATIC CONVERSION FAILED IN SOME WAY");
LOGGER.warn("** please restart the server and if the problem persists, remove the directory '{}'", (Object)worldPlayerDirectory.getPath());
return false;
}
return true;
}
private static File getWorldPlayersDirectory(MinecraftServer server) {
return server.getWorldPath(LevelResource.PLAYER_OLD_DATA_DIR).toFile();
}
private static void renameOldFile(File file) {
File newFile = new File(file.getName() + ".converted");
file.renameTo(newFile);
}
private static Date parseDate(String dateString, Date defaultValue) {
Date parsedDate;
try {
parsedDate = BanListEntry.DATE_FORMAT.parse(dateString);
}
catch (ParseException ignored) {
parsedDate = defaultValue;
}
return parsedDate;
}
private static class ConversionError
extends RuntimeException {
private ConversionError(String message, Throwable cause) {
super(message, cause);
}
private ConversionError(String message) {
super(message);
}
}
}