package ru.gravit.launcher.profiles; import ru.gravit.launcher.LauncherAPI; import ru.gravit.launcher.hasher.FileNameMatcher; import ru.gravit.launcher.hasher.HashedDir; import ru.gravit.utils.helper.IOHelper; import ru.gravit.utils.helper.VerifyHelper; import java.io.IOException; import java.net.InetSocketAddress; import java.util.*; @SuppressWarnings("ComparableImplementedButEqualsNotOverridden") public final class ClientProfile implements Comparable { public ClientProfile(String version, String assetIndex, int sortIndex, String title, String serverAddress, int serverPort, boolean updateFastCheck, boolean useWhitelist, String mainClass) { this.version = version; this.assetIndex = assetIndex; this.sortIndex = sortIndex; this.title = title; this.serverAddress = serverAddress; this.serverPort = serverPort; this.updateFastCheck = updateFastCheck; this.useWhitelist = useWhitelist; this.mainClass = mainClass; } public ClientProfile() { } @LauncherAPI public enum Version { MC147("1.4.7", 51), MC152("1.5.2", 61), MC164("1.6.4", 78), MC172("1.7.2", 4), MC1710("1.7.10", 5), MC189("1.8.9", 47), MC194("1.9.4", 110), MC1102("1.10.2", 210), MC1112("1.11.2", 316), MC1122("1.12.2", 340), MC113("1.13", 393), MC1131("1.13.1", 401), MC1132("1.13.2", 402); private static final Map VERSIONS; static { Version[] versionsValues = values(); VERSIONS = new HashMap<>(versionsValues.length); for (Version version : versionsValues) VERSIONS.put(version.name, version); } public static Version byName(String name) { return VerifyHelper.getMapValue(VERSIONS, name, String.format("Unknown client version: '%s'", name)); } public final String name; public final int protocol; Version(String name, int protocol) { this.name = name; this.protocol = protocol; } @Override public String toString() { return "Minecraft " + name; } } public static final boolean profileCaseSensitive = Boolean.getBoolean("launcher.clientProfile.caseSensitive"); private static final FileNameMatcher ASSET_MATCHER = new FileNameMatcher( new String[0], new String[]{"indexes", "objects"}, new String[0]); // Version @LauncherAPI private String version; @LauncherAPI private String assetIndex; @LauncherAPI private String dir; @LauncherAPI private String assetDir; // Client @LauncherAPI private int sortIndex; @LauncherAPI private String title; @LauncherAPI private String serverAddress; @LauncherAPI private int serverPort; public static class OptionalFile { @LauncherAPI public String file; @LauncherAPI public boolean mark; @LauncherAPI public String name; @LauncherAPI public String info; @LauncherAPI public int sunTreeLevel = 1; @LauncherAPI public boolean onlyOne = false; @LauncherAPI public int onlyOneGroup = 1; public OptionalFile(String file, boolean mark) { this.file = file; this.mark = mark; } public OptionalFile(String file) { this.file = file; this.mark = false; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; OptionalFile that = (OptionalFile) o; return Objects.equals(file, that.file); } @Override public int hashCode() { return Objects.hash(file); } } // Updater and client watch service @LauncherAPI private final List update = new ArrayList<>(); @LauncherAPI private final List updateExclusions = new ArrayList<>(); @LauncherAPI private final List updateShared = new ArrayList<>(); @LauncherAPI private final List updateVerify = new ArrayList<>(); @LauncherAPI private final Set updateOptional = new HashSet<>(); @LauncherAPI private boolean updateFastCheck; @LauncherAPI private boolean useWhitelist; // Client launcher @LauncherAPI private String mainClass; @LauncherAPI private final List jvmArgs = new ArrayList<>(); @LauncherAPI private final List classPath = new ArrayList<>(); @LauncherAPI private final List clientArgs = new ArrayList<>(); @LauncherAPI private final List whitelist = new ArrayList<>(); @Override public int compareTo(ClientProfile o) { return Integer.compare(getSortIndex(), o.getSortIndex()); } @LauncherAPI public String getAssetIndex() { return assetIndex; } @LauncherAPI public FileNameMatcher getAssetUpdateMatcher() { return getVersion().compareTo(Version.MC1710) >= 0 ? ASSET_MATCHER : null; } @LauncherAPI public String[] getClassPath() { return classPath.toArray(new String[0]); } @LauncherAPI public String[] getClientArgs() { return clientArgs.toArray(new String[0]); } @LauncherAPI public String getDir() { return dir; } public void setDir(String dir) { this.dir = dir; } @LauncherAPI public String getAssetDir() { return assetDir; } @LauncherAPI public FileNameMatcher getClientUpdateMatcher(/*boolean excludeOptional*/) { String[] updateArray = update.toArray(new String[0]); String[] verifyArray = updateVerify.toArray(new String[0]); List excludeList; //if(excludeOptional) //{ // excludeList = new ArrayList<>(); // excludeList.addAll(updateExclusions); // excludeList.addAll(updateOptional); //} //else excludeList = updateExclusions; String[] exclusionsArray = excludeList.toArray(new String[0]); return new FileNameMatcher(updateArray, verifyArray, exclusionsArray); } @LauncherAPI public String[] getJvmArgs() { return jvmArgs.toArray(new String[0]); } @LauncherAPI public String getMainClass() { return mainClass; } @LauncherAPI public String getServerAddress() { return serverAddress; } @LauncherAPI public Set getOptional() { return updateOptional; } @LauncherAPI public OptionalFile getOptionalFile(String file) { for(OptionalFile f : updateOptional) if(f.file.equals(file)) return f; return null; } @LauncherAPI public Collection getShared() { return updateShared; } @LauncherAPI public void markOptional(String opt) { if (!updateOptional.contains(new OptionalFile(opt))) throw new SecurityException(String.format("Optional mod %s not found in optionalList", opt)); updateOptional.forEach(e -> { if (e.file.equals(opt)) e.mark = true; }); } @LauncherAPI public void unmarkOptional(String opt) { if (!updateOptional.contains(new OptionalFile(opt))) throw new SecurityException(String.format("Optional mod %s not found in optionalList", opt)); updateOptional.forEach(e -> { if (e.file.equals(opt)) e.mark = false; }); } public void pushOptional(HashedDir dir, boolean digest) throws IOException { for (OptionalFile opt : updateOptional) { if (!opt.mark) dir.removeR(opt.file); } } @LauncherAPI public int getServerPort() { return serverPort; } @LauncherAPI public InetSocketAddress getServerSocketAddress() { return InetSocketAddress.createUnresolved(getServerAddress(), getServerPort()); } @LauncherAPI public int getSortIndex() { return sortIndex; } @LauncherAPI public String getTitle() { return title; } @LauncherAPI public Version getVersion() { return Version.byName(version); } @LauncherAPI public boolean isUpdateFastCheck() { return updateFastCheck; } @LauncherAPI public boolean isWhitelistContains(String username) { if (!useWhitelist) return true; return whitelist.stream().anyMatch(profileCaseSensitive ? e -> e.equals(username) : e -> e.equalsIgnoreCase(username)); } @LauncherAPI public void setTitle(String title) { this.title = title; } @LauncherAPI public void setVersion(Version version) { this.version = version.name; } @Override public String toString() { return title; } @LauncherAPI public void verify() { // Version getVersion(); IOHelper.verifyFileName(getAssetIndex()); // Client VerifyHelper.verify(getTitle(), VerifyHelper.NOT_EMPTY, "Profile title can't be empty"); VerifyHelper.verify(getServerAddress(), VerifyHelper.NOT_EMPTY, "Server address can't be empty"); VerifyHelper.verifyInt(getServerPort(), VerifyHelper.range(0, 65535), "Illegal server port: " + getServerPort()); // Client launcher VerifyHelper.verify(getTitle(), VerifyHelper.NOT_EMPTY, "Main class can't be empty"); } }