mirror of
https://github.com/GravitLauncher/Launcher
synced 2025-04-19 14:33:04 +03:00
[Feature] Union commands
This commit is contained in:
parent
82b6b2d253
commit
64defdcc58
6 changed files with 209 additions and 3 deletions
|
@ -0,0 +1,63 @@
|
||||||
|
package pro.gravit.launchserver.command.experimental;
|
||||||
|
|
||||||
|
import pro.gravit.launcher.Launcher;
|
||||||
|
import pro.gravit.launcher.profiles.ClientProfile;
|
||||||
|
import pro.gravit.launchserver.LaunchServer;
|
||||||
|
import pro.gravit.launchserver.command.Command;
|
||||||
|
import pro.gravit.utils.helper.IOHelper;
|
||||||
|
|
||||||
|
import java.io.Writer;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class UnionAssetsCommand extends Command {
|
||||||
|
public UnionAssetsCommand(LaunchServer server) {
|
||||||
|
super(server);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getArgsDescription() {
|
||||||
|
return "[]";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUsageDescription() {
|
||||||
|
return "union assets";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invoke(String... args) throws Exception {
|
||||||
|
List<String> checkedDirs = new ArrayList<>();
|
||||||
|
var assetDir = server.updatesDir.resolve("assets");
|
||||||
|
if(Files.notExists(assetDir)) {
|
||||||
|
Files.createDirectories(assetDir);
|
||||||
|
}
|
||||||
|
for(ClientProfile profile : server.getProfiles()) {
|
||||||
|
var visitor = new UnionLibrariesCommand.ListFileVisitor();
|
||||||
|
if(checkedDirs.contains(profile.getAssetDir())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var dir = server.updatesDir.resolve(profile.getAssetDir());
|
||||||
|
IOHelper.walk(dir, visitor, false);
|
||||||
|
var list = visitor.getList();
|
||||||
|
for(Path p : list) {
|
||||||
|
Path relativized = dir.relativize(p);
|
||||||
|
Path target = assetDir.resolve(relativized);
|
||||||
|
if(Files.notExists(target)) {
|
||||||
|
IOHelper.createParentDirs(target);
|
||||||
|
Files.move(p, target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IOHelper.deleteDir(dir, true);
|
||||||
|
profile.setAssetDir("assets");
|
||||||
|
checkedDirs.add(profile.getAssetDir());
|
||||||
|
try (Writer w = IOHelper.newWriter(server.profilesDir.resolve(profile.getTitle().concat(".json")))) {
|
||||||
|
Launcher.gsonManager.configGson.toJson(profile, w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
server.syncProfilesDir();
|
||||||
|
server.updatesManager.syncUpdatesDir(null);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,118 @@
|
||||||
|
package pro.gravit.launchserver.command.experimental;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import pro.gravit.launcher.Launcher;
|
||||||
|
import pro.gravit.launcher.hasher.HashedDir;
|
||||||
|
import pro.gravit.launcher.profiles.ClientProfile;
|
||||||
|
import pro.gravit.launchserver.LaunchServer;
|
||||||
|
import pro.gravit.launchserver.command.Command;
|
||||||
|
import pro.gravit.utils.helper.IOHelper;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.Writer;
|
||||||
|
import java.nio.file.*;
|
||||||
|
import java.nio.file.attribute.BasicFileAttributes;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class UnionLibrariesCommand extends Command {
|
||||||
|
private final Logger logger = LogManager.getLogger();
|
||||||
|
public UnionLibrariesCommand(LaunchServer server) {
|
||||||
|
super(server);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getArgsDescription() {
|
||||||
|
return "[]";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUsageDescription() {
|
||||||
|
return "union libraries";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invoke(String... args) throws Exception {
|
||||||
|
Map<Path, List<Path>> libraries = new HashMap<>();
|
||||||
|
logger.info("Resolve libraries");
|
||||||
|
Path librariesDir = server.updatesDir.resolve("libraries");
|
||||||
|
for(String dir : server.updatesManager.getUpdatesList()) {
|
||||||
|
var visitor = new ListFileVisitor();
|
||||||
|
var updateDir = server.updatesDir.resolve(dir).resolve("libraries");
|
||||||
|
if(Files.notExists(updateDir)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
IOHelper.walk(updateDir, visitor, false);
|
||||||
|
var list = visitor.getList();
|
||||||
|
for(Path p : list) {
|
||||||
|
var p1 = updateDir.relativize(p);
|
||||||
|
var l = libraries.computeIfAbsent(p1, k -> new ArrayList<>(8));
|
||||||
|
l.add(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(Files.notExists(librariesDir)) {
|
||||||
|
Files.createDirectories(librariesDir);
|
||||||
|
}
|
||||||
|
logger.info("Move libraries");
|
||||||
|
libraries.forEach((k,v) -> {
|
||||||
|
ClientProfile.ClientProfileLibrary library;
|
||||||
|
String name = ClientProfile.ClientProfileLibrary.convertMavenPathToName(k.toString());
|
||||||
|
if(name == null) {
|
||||||
|
name = k.getFileName().toString();
|
||||||
|
}
|
||||||
|
if(v.size() == 1) {
|
||||||
|
library = new ClientProfile.ClientProfileLibrary("", name, k.toString());
|
||||||
|
} else {
|
||||||
|
library = new ClientProfile.ClientProfileLibrary("libraries", name, k.toString());
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Path target = librariesDir.resolve(k);
|
||||||
|
Path source = v.get(0);
|
||||||
|
if(v.size() > 1 && Files.notExists(target)) {
|
||||||
|
IOHelper.createParentDirs(target);
|
||||||
|
logger.debug("Move {} to {}", source, target);
|
||||||
|
Files.move(source, target);
|
||||||
|
}
|
||||||
|
for(Path p : v) {
|
||||||
|
var dirName = server.updatesDir.relativize(p).getName(0).toString();
|
||||||
|
logger.debug("dirName {}", dirName);
|
||||||
|
for(ClientProfile profile : server.getProfiles()) {
|
||||||
|
if(profile.getDir().equals(dirName)) {
|
||||||
|
logger.debug("Found profile {}", profile.getTitle());
|
||||||
|
var list = profile.getLibraries();
|
||||||
|
list.add(library);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(p != source) {
|
||||||
|
logger.debug("Delete {}", p);
|
||||||
|
Files.delete(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logger.info("Library {} found {} duplicated", k, v.size());
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.error(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
logger.info("Write profiles");
|
||||||
|
for(ClientProfile profile : server.getProfiles()) {
|
||||||
|
try (Writer w = IOHelper.newWriter(server.profilesDir.resolve(profile.getTitle().concat(".json")))) {
|
||||||
|
Launcher.gsonManager.configGson.toJson(profile, w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
server.syncProfilesDir();
|
||||||
|
server.updatesManager.syncUpdatesDir(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ListFileVisitor extends SimpleFileVisitor<Path> {
|
||||||
|
private final List<Path> list = new LinkedList<>();
|
||||||
|
@Override
|
||||||
|
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
||||||
|
list.add(file);
|
||||||
|
return super.visitFile(file, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Path> getList() {
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,6 +5,8 @@
|
||||||
import pro.gravit.launchserver.command.basic.RestartCommand;
|
import pro.gravit.launchserver.command.basic.RestartCommand;
|
||||||
import pro.gravit.launchserver.command.basic.StopCommand;
|
import pro.gravit.launchserver.command.basic.StopCommand;
|
||||||
import pro.gravit.launchserver.command.basic.VersionCommand;
|
import pro.gravit.launchserver.command.basic.VersionCommand;
|
||||||
|
import pro.gravit.launchserver.command.experimental.UnionAssetsCommand;
|
||||||
|
import pro.gravit.launchserver.command.experimental.UnionLibrariesCommand;
|
||||||
import pro.gravit.launchserver.command.hash.*;
|
import pro.gravit.launchserver.command.hash.*;
|
||||||
import pro.gravit.launchserver.command.modules.LoadModuleCommand;
|
import pro.gravit.launchserver.command.modules.LoadModuleCommand;
|
||||||
import pro.gravit.launchserver.command.modules.ModulesCommand;
|
import pro.gravit.launchserver.command.modules.ModulesCommand;
|
||||||
|
@ -62,5 +64,11 @@ public static void registerCommands(pro.gravit.utils.command.CommandHandler hand
|
||||||
service.registerCommand("token", new TokenCommand(server));
|
service.registerCommand("token", new TokenCommand(server));
|
||||||
Category serviceCategory = new Category(service, "service", "Managing LaunchServer Components");
|
Category serviceCategory = new Category(service, "service", "Managing LaunchServer Components");
|
||||||
handler.registerCategory(serviceCategory);
|
handler.registerCategory(serviceCategory);
|
||||||
|
|
||||||
|
BaseCommandCategory experimental = new BaseCommandCategory();
|
||||||
|
experimental.registerCommand("unionlibraries", new UnionLibrariesCommand(server));
|
||||||
|
experimental.registerCommand("unionassets", new UnionAssetsCommand(server));
|
||||||
|
Category experimentalCategory = new Category(experimental, "Experimental", "Experimental features");
|
||||||
|
handler.registerCategory(experimentalCategory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -334,8 +334,8 @@ private static Stream<Path> resolveZonedClassPath(Path clientDir, List<ClientLau
|
||||||
for(ClientProfile.ClientProfileLibrary library : libraries) {
|
for(ClientProfile.ClientProfileLibrary library : libraries) {
|
||||||
if(library.type == ClientProfile.ClientProfileLibrary.LibraryType.CLASSPATH) {
|
if(library.type == ClientProfile.ClientProfileLibrary.LibraryType.CLASSPATH) {
|
||||||
Path zone = null;
|
Path zone = null;
|
||||||
if(library.zone == null || library.zone.isEmpty()) {
|
if(library.zone == null || library.zone.isEmpty() || library.zone.equals("@")) {
|
||||||
zone = clientDir;
|
zone = clientDir.resolve("libraries");
|
||||||
} else {
|
} else {
|
||||||
for(ClientLauncherProcess.ClientParams.ClientZoneInfo info : zones) {
|
for(ClientLauncherProcess.ClientParams.ClientZoneInfo info : zones) {
|
||||||
if(info.name.equals(library.zone)) {
|
if(info.name.equals(library.zone)) {
|
||||||
|
@ -348,6 +348,7 @@ private static Stream<Path> resolveZonedClassPath(Path clientDir, List<ClientLau
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Path path = zone.resolve(library.path);
|
Path path = zone.resolve(library.path);
|
||||||
|
LogHelper.debug("Library %s (zone %s path %s) resolved in %s", library.name, library.zone, library.path, path);
|
||||||
builder.accept(path);
|
builder.accept(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
public final class ClientProfile implements Comparable<ClientProfile> {
|
public final class ClientProfile implements Comparable<ClientProfile> {
|
||||||
private static final FileNameMatcher ASSET_MATCHER = new FileNameMatcher(
|
private static final FileNameMatcher ASSET_MATCHER = new FileNameMatcher(
|
||||||
|
@ -83,7 +85,13 @@ public final class ClientProfile implements Comparable<ClientProfile> {
|
||||||
@LauncherNetworkAPI
|
@LauncherNetworkAPI
|
||||||
private String mainClass;
|
private String mainClass;
|
||||||
|
|
||||||
|
public ClientProfile setAssetDir(String assetDir) {
|
||||||
|
this.assetDir = assetDir;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public static class ClientProfileLibrary {
|
public static class ClientProfileLibrary {
|
||||||
|
private static Pattern MAVEN_PATTERN = Pattern.compile("(?<group>.)/(?<name>.)/(?<version>.)/(?<jarname>.).jar");
|
||||||
public final String zone;
|
public final String zone;
|
||||||
public final String name;
|
public final String name;
|
||||||
public final String path;
|
public final String path;
|
||||||
|
@ -130,6 +138,14 @@ public ClientProfileLibrary(String name) {
|
||||||
this.type = LibraryType.CLASSPATH;
|
this.type = LibraryType.CLASSPATH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String convertMavenPathToName(String path) {
|
||||||
|
Matcher matcher = MAVEN_PATTERN.matcher(path);
|
||||||
|
if(matcher.matches()) {
|
||||||
|
return String.format("%s:%s:%s", matcher.group("group"), matcher.group("name"), matcher.group("version"));
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public static String convertMavenNameToPath(String name) {
|
public static String convertMavenNameToPath(String name) {
|
||||||
String[] mavenIdSplit = name.split(":");
|
String[] mavenIdSplit = name.split(":");
|
||||||
if(mavenIdSplit.length < 3) {
|
if(mavenIdSplit.length < 3) {
|
||||||
|
|
|
@ -60,10 +60,10 @@ protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Except
|
||||||
final WebSocketFrame frame = (WebSocketFrame) msg;
|
final WebSocketFrame frame = (WebSocketFrame) msg;
|
||||||
if (frame instanceof TextWebSocketFrame) {
|
if (frame instanceof TextWebSocketFrame) {
|
||||||
final TextWebSocketFrame textFrame = (TextWebSocketFrame) frame;
|
final TextWebSocketFrame textFrame = (TextWebSocketFrame) frame;
|
||||||
clientJSONPoint.onMessage(textFrame.text());
|
|
||||||
if (LogHelper.isDevEnabled()) {
|
if (LogHelper.isDevEnabled()) {
|
||||||
LogHelper.dev("Message: %s", textFrame.text());
|
LogHelper.dev("Message: %s", textFrame.text());
|
||||||
}
|
}
|
||||||
|
clientJSONPoint.onMessage(textFrame.text());
|
||||||
// uncomment to print request
|
// uncomment to print request
|
||||||
// logger.info(textFrame.text());
|
// logger.info(textFrame.text());
|
||||||
} else if ((frame instanceof PingWebSocketFrame)) {
|
} else if ((frame instanceof PingWebSocketFrame)) {
|
||||||
|
|
Loading…
Reference in a new issue