mirror of
https://github.com/GravitLauncher/Launcher
synced 2024-12-23 17:11:39 +03:00
Merge branch 'release/5.0.1'
This commit is contained in:
commit
e55200f5eb
39 changed files with 711 additions and 262 deletions
|
@ -24,7 +24,7 @@ build:
|
||||||
- ./gradlew assemble
|
- ./gradlew assemble
|
||||||
artifacts:
|
artifacts:
|
||||||
paths:
|
paths:
|
||||||
- LaunchServer/build/libs/*.jar
|
- LaunchServer/build/libs/*
|
||||||
- ServerWrapper/build/libs/*.jar
|
- ServerWrapper/build/libs/*.jar
|
||||||
expire_in: 1 week
|
expire_in: 1 week
|
||||||
|
|
||||||
|
|
|
@ -263,9 +263,15 @@ public static class ExeConf {
|
||||||
public String txtFileVersion;
|
public String txtFileVersion;
|
||||||
public String txtProductVersion;
|
public String txtProductVersion;
|
||||||
}
|
}
|
||||||
|
public static class NettyUpdatesBind
|
||||||
|
{
|
||||||
|
public String url;
|
||||||
|
public boolean zip;
|
||||||
|
}
|
||||||
|
|
||||||
public class LauncherConf {
|
public class LauncherConf {
|
||||||
public String guardType;
|
public String guardType;
|
||||||
|
public boolean attachLibraryBeforeProGuard;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NettyConfig {
|
public class NettyConfig {
|
||||||
|
@ -276,7 +282,7 @@ public class NettyConfig {
|
||||||
public String downloadURL;
|
public String downloadURL;
|
||||||
public String launcherEXEURL;
|
public String launcherEXEURL;
|
||||||
public String address;
|
public String address;
|
||||||
public Map<String, String> bindings = new HashMap<>();
|
public Map<String, NettyUpdatesBind> bindings = new HashMap<>();
|
||||||
public NettyPerformanceConfig performance;
|
public NettyPerformanceConfig performance;
|
||||||
public NettyBindAddress[] binds;
|
public NettyBindAddress[] binds;
|
||||||
public LogLevel logLevel = LogLevel.DEBUG;
|
public LogLevel logLevel = LogLevel.DEBUG;
|
||||||
|
|
|
@ -27,6 +27,7 @@ public class MysqlHWIDHandler extends HWIDHandler {
|
||||||
private String hwidFieldHWDiskSerial;
|
private String hwidFieldHWDiskSerial;
|
||||||
private String hwidFieldProcessorID;
|
private String hwidFieldProcessorID;
|
||||||
private String hwidFieldBanned;
|
private String hwidFieldBanned;
|
||||||
|
private String hwidFieldMAC;
|
||||||
|
|
||||||
private String queryHwids;
|
private String queryHwids;
|
||||||
private String[] paramsHwids;
|
private String[] paramsHwids;
|
||||||
|
@ -37,7 +38,7 @@ public class MysqlHWIDHandler extends HWIDHandler {
|
||||||
private String banMessage;
|
private String banMessage;
|
||||||
|
|
||||||
private boolean compareMode = false;
|
private boolean compareMode = false;
|
||||||
//Using queryHWID "queryHwids": "SELECT * FROM `users_hwids` WHERE `totalMemory` = ? or `serialNumber` = ? or `HWDiskSerial` = ? or `processorID` = ?"
|
//Using queryHWID "queryHwids": "SELECT * FROM `users_hwids` WHERE `totalMemory` = ? or `serialNumber` = ? or `HWDiskSerial` = ? or `processorID` = ? or `MACAddr` = ?"
|
||||||
private int compare = 50; //При наборе схожести в 50 очков
|
private int compare = 50; //При наборе схожести в 50 очков
|
||||||
private boolean oneCompareMode = false;
|
private boolean oneCompareMode = false;
|
||||||
|
|
||||||
|
@ -51,6 +52,7 @@ public class MysqlHWIDHandler extends HWIDHandler {
|
||||||
`serialNumber` varchar(64) NOT NULL,
|
`serialNumber` varchar(64) NOT NULL,
|
||||||
`HWDiskSerial` varchar(64) NOT NULL,
|
`HWDiskSerial` varchar(64) NOT NULL,
|
||||||
`processorID` varchar(64) NOT NULL,
|
`processorID` varchar(64) NOT NULL,
|
||||||
|
`MACAddr` varchar(64) NOT NULL,
|
||||||
`isBanned` tinyint(1) NOT NULL DEFAULT '0'
|
`isBanned` tinyint(1) NOT NULL DEFAULT '0'
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
|
|
||||||
|
@ -90,7 +92,7 @@ public void check0(HWID hwid, String username) throws HWIDException {
|
||||||
public void onUpdateInfo(OshiHWID hwid, String username, Connection c) throws HWIDException {
|
public void onUpdateInfo(OshiHWID hwid, String username, Connection c) throws HWIDException {
|
||||||
try (PreparedStatement a = c.prepareStatement(queryHwids)) {
|
try (PreparedStatement a = c.prepareStatement(queryHwids)) {
|
||||||
|
|
||||||
String[] replaceParams = {"totalMemory", String.valueOf(hwid.totalMemory), "serialNumber", hwid.serialNumber, "HWDiskSerial", hwid.HWDiskSerial, "processorID", hwid.processorID};
|
String[] replaceParams = {"totalMemory", String.valueOf(hwid.totalMemory), "serialNumber", hwid.serialNumber, "HWDiskSerial", hwid.HWDiskSerial, "processorID", hwid.processorID, "MAC", hwid.macAddr};
|
||||||
for (int i = 0; i < paramsHwids.length; i++) {
|
for (int i = 0; i < paramsHwids.length; i++) {
|
||||||
a.setString(i + 1, CommonHelper.replace(paramsHwids[i], replaceParams));
|
a.setString(i + 1, CommonHelper.replace(paramsHwids[i], replaceParams));
|
||||||
}
|
}
|
||||||
|
@ -113,12 +115,13 @@ public void onUpdateInfo(OshiHWID hwid, String username, Connection c) throws HW
|
||||||
throw new HWIDException(banMessage);
|
throw new HWIDException(banMessage);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ps = c.prepareStatement(String.format("INSERT INTO `%s` (`%s`, `%s`, `%s`, `%s`) VALUES (?, ?, ?, ?);",
|
ps = c.prepareStatement(String.format("INSERT INTO `%s` (`%s`, `%s`, `%s`, `%s`, `%s`) VALUES (?, ?, ?, ?, ?);",
|
||||||
tableHwids, hwidFieldTotalMemory, hwidFieldSerialNumber, hwidFieldHWDiskSerial, hwidFieldProcessorID));
|
tableHwids, hwidFieldTotalMemory, hwidFieldSerialNumber, hwidFieldHWDiskSerial, hwidFieldProcessorID, hwidFieldMAC));
|
||||||
ps.setString(1, String.valueOf(hwid.totalMemory));
|
ps.setString(1, String.valueOf(hwid.totalMemory));
|
||||||
ps.setString(2, hwid.serialNumber);
|
ps.setString(2, hwid.serialNumber);
|
||||||
ps.setString(3, hwid.HWDiskSerial);
|
ps.setString(3, hwid.HWDiskSerial);
|
||||||
ps.setString(4, hwid.processorID);
|
ps.setString(4, hwid.processorID);
|
||||||
|
ps.setString(5, hwid.macAddr);
|
||||||
ps.setQueryTimeout(MySQLSourceConfig.TIMEOUT);
|
ps.setQueryTimeout(MySQLSourceConfig.TIMEOUT);
|
||||||
ps.executeUpdate();
|
ps.executeUpdate();
|
||||||
|
|
||||||
|
@ -135,7 +138,7 @@ public void onUpdateInfo(OshiHWID hwid, String username, Connection c) throws HW
|
||||||
|
|
||||||
public void onCheckInfo(OshiHWID hwid, String username, Connection c) throws HWIDException {
|
public void onCheckInfo(OshiHWID hwid, String username, Connection c) throws HWIDException {
|
||||||
try (PreparedStatement a = c.prepareStatement(queryHwids)) {
|
try (PreparedStatement a = c.prepareStatement(queryHwids)) {
|
||||||
String[] replaceParams = {"totalMemory", String.valueOf(hwid.totalMemory), "serialNumber", hwid.serialNumber, "HWDiskSerial", hwid.HWDiskSerial, "processorID", hwid.processorID};
|
String[] replaceParams = {"totalMemory", String.valueOf(hwid.totalMemory), "serialNumber", hwid.serialNumber, "HWDiskSerial", hwid.HWDiskSerial, "processorID", hwid.processorID, "MAC", hwid.macAddr};
|
||||||
for (int i = 0; i < paramsHwids.length; i++) {
|
for (int i = 0; i < paramsHwids.length; i++) {
|
||||||
a.setString(i + 1, CommonHelper.replace(paramsHwids[i], replaceParams));
|
a.setString(i + 1, CommonHelper.replace(paramsHwids[i], replaceParams));
|
||||||
}
|
}
|
||||||
|
@ -149,7 +152,7 @@ public void onCheckInfo(OshiHWID hwid, String username, Connection c) throws HWI
|
||||||
db_hwid.processorID = set.getString(hwidFieldProcessorID);
|
db_hwid.processorID = set.getString(hwidFieldProcessorID);
|
||||||
db_hwid.HWDiskSerial = set.getString(hwidFieldHWDiskSerial);
|
db_hwid.HWDiskSerial = set.getString(hwidFieldHWDiskSerial);
|
||||||
db_hwid.totalMemory = Long.valueOf(set.getString(hwidFieldTotalMemory));
|
db_hwid.totalMemory = Long.valueOf(set.getString(hwidFieldTotalMemory));
|
||||||
db_hwid.macAddr = "";
|
db_hwid.macAddr = set.getString(hwidFieldMAC);
|
||||||
LogHelper.dev("Compare HWID: %s vs %s", hwid.getSerializeString(), db_hwid.getSerializeString());
|
LogHelper.dev("Compare HWID: %s vs %s", hwid.getSerializeString(), db_hwid.getSerializeString());
|
||||||
int compare_point = hwid.compare(db_hwid);
|
int compare_point = hwid.compare(db_hwid);
|
||||||
if (compare_point < compare) continue;
|
if (compare_point < compare) continue;
|
||||||
|
@ -177,7 +180,7 @@ public void setIsBanned(HWID hwid, boolean isBanned) {
|
||||||
OshiHWID oshiHWID = (OshiHWID) hwid;
|
OshiHWID oshiHWID = (OshiHWID) hwid;
|
||||||
try (Connection c = mySQLHolder.getConnection()) {
|
try (Connection c = mySQLHolder.getConnection()) {
|
||||||
try (PreparedStatement a = c.prepareStatement(queryBan)) {
|
try (PreparedStatement a = c.prepareStatement(queryBan)) {
|
||||||
String[] replaceParamsUpd = {"totalMemory", String.valueOf(oshiHWID.totalMemory), "serialNumber", oshiHWID.serialNumber, "HWDiskSerial", oshiHWID.HWDiskSerial, "processorID", oshiHWID.processorID, "isBanned", isBanned ? "1" : "0"};
|
String[] replaceParamsUpd = {"totalMemory", String.valueOf(oshiHWID.totalMemory), "serialNumber", oshiHWID.serialNumber, "HWDiskSerial", oshiHWID.HWDiskSerial, "processorID", oshiHWID.processorID, "MAC", oshiHWID.macAddr, "isBanned", isBanned ? "1" : "0"};
|
||||||
for (int i = 0; i < paramsBan.length; i++) {
|
for (int i = 0; i < paramsBan.length; i++) {
|
||||||
a.setString(i + 1, CommonHelper.replace(paramsBan[i], replaceParamsUpd));
|
a.setString(i + 1, CommonHelper.replace(paramsBan[i], replaceParamsUpd));
|
||||||
}
|
}
|
||||||
|
@ -231,6 +234,7 @@ public List<HWID> getHwid(String username) {
|
||||||
oshiHWID.serialNumber = rs.getString(hwidFieldSerialNumber);
|
oshiHWID.serialNumber = rs.getString(hwidFieldSerialNumber);
|
||||||
oshiHWID.HWDiskSerial = rs.getString(hwidFieldHWDiskSerial);
|
oshiHWID.HWDiskSerial = rs.getString(hwidFieldHWDiskSerial);
|
||||||
oshiHWID.processorID = rs.getString(hwidFieldProcessorID);
|
oshiHWID.processorID = rs.getString(hwidFieldProcessorID);
|
||||||
|
oshiHWID.macAddr = rs.getString(hwidFieldMAC);
|
||||||
list.add(oshiHWID);
|
list.add(oshiHWID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,6 +83,12 @@ public void setSecretKey(String key) {
|
||||||
body.append("\";");
|
body.append("\";");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setOemUnlockKey(String key) {
|
||||||
|
body.append("this.oemUnlockKey = \"");
|
||||||
|
body.append(key);
|
||||||
|
body.append("\";");
|
||||||
|
}
|
||||||
|
|
||||||
public void setGuardType(String key) {
|
public void setGuardType(String key) {
|
||||||
body.append("this.guardType = \"");
|
body.append("this.guardType = \"");
|
||||||
body.append(key);
|
body.append(key);
|
||||||
|
|
|
@ -42,10 +42,11 @@ public JARLauncherBinary(LaunchServer server) throws IOException {
|
||||||
public void init() {
|
public void init() {
|
||||||
tasks.add(new PrepareBuildTask(server));
|
tasks.add(new PrepareBuildTask(server));
|
||||||
tasks.add(new MainBuildTask(server));
|
tasks.add(new MainBuildTask(server));
|
||||||
|
if(server.config.launcher.attachLibraryBeforeProGuard) tasks.add(new AttachJarsTask(server));
|
||||||
tasks.add(new ProGuardBuildTask(server));
|
tasks.add(new ProGuardBuildTask(server));
|
||||||
tasks.add(new AdditionalFixesApplyTask(server));
|
tasks.add(new AdditionalFixesApplyTask(server));
|
||||||
tasks.add(new RadonBuildTask(server));
|
tasks.add(new RadonBuildTask(server));
|
||||||
tasks.add(new AttachJarsTask(server));
|
if(!server.config.launcher.attachLibraryBeforeProGuard) tasks.add(new AttachJarsTask(server));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -137,6 +137,8 @@ public Path process(Path inputJar) throws IOException {
|
||||||
jaConfigurator.setGuardType(server.config.launcher.guardType);
|
jaConfigurator.setGuardType(server.config.launcher.guardType);
|
||||||
jaConfigurator.setWarningMissArchJava(server.config.isWarningMissArchJava);
|
jaConfigurator.setWarningMissArchJava(server.config.isWarningMissArchJava);
|
||||||
jaConfigurator.setEnv(server.config.env);
|
jaConfigurator.setEnv(server.config.env);
|
||||||
|
if(server.runtime.oemUnlockKey == null) server.runtime.oemUnlockKey = SecurityHelper.randomStringToken();
|
||||||
|
jaConfigurator.setOemUnlockKey(server.runtime.oemUnlockKey);
|
||||||
server.buildHookManager.registerAllClientModuleClass(jaConfigurator);
|
server.buildHookManager.registerAllClientModuleClass(jaConfigurator);
|
||||||
reader.getCp().add(new JarFile(inputJar.toFile()));
|
reader.getCp().add(new JarFile(inputJar.toFile()));
|
||||||
server.launcherBinary.coreLibs.forEach(e -> {
|
server.launcherBinary.coreLibs.forEach(e -> {
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
public class LaunchServerRuntimeConfig {
|
public class LaunchServerRuntimeConfig {
|
||||||
public String clientToken;
|
public String clientToken;
|
||||||
|
public String oemUnlockKey;
|
||||||
|
|
||||||
public void verify() {
|
public void verify() {
|
||||||
if (clientToken == null) LogHelper.error("[RuntimeConfig] clientToken must not be null");
|
if (clientToken == null) LogHelper.error("[RuntimeConfig] clientToken must not be null");
|
||||||
|
|
|
@ -39,7 +39,13 @@ public void execute(ChannelHandlerContext ctx, Client client) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String url = LaunchServer.server.config.netty.downloadURL.replace("%dirname%", dirName);
|
String url = LaunchServer.server.config.netty.downloadURL.replace("%dirname%", dirName);
|
||||||
if (server.config.netty.bindings.get(dirName) != null) url = server.config.netty.bindings.get(dirName);
|
boolean zip = false;
|
||||||
service.sendObject(ctx, new UpdateRequestEvent(dir.object, url));
|
if (server.config.netty.bindings.get(dirName) != null)
|
||||||
|
{
|
||||||
|
LaunchServer.NettyUpdatesBind bind = server.config.netty.bindings.get(dirName);
|
||||||
|
url = bind.url;
|
||||||
|
zip = bind.zip;
|
||||||
|
}
|
||||||
|
service.sendObject(ctx, new UpdateRequestEvent(dir.object, url, zip));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ var profilesList = [];
|
||||||
var movePoint = null;
|
var movePoint = null;
|
||||||
var pingers = {};
|
var pingers = {};
|
||||||
var loginData;
|
var loginData;
|
||||||
// Variable which contains all types of auth. Appending data at line 255
|
|
||||||
var authTypes = {};
|
var authTypes = {};
|
||||||
|
|
||||||
function initLauncher() {
|
function initLauncher() {
|
||||||
|
@ -195,7 +194,6 @@ function goAuth(event) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get auth
|
|
||||||
var auth = authOptions.getSelectionModel().getSelectedItem();
|
var auth = authOptions.getSelectionModel().getSelectedItem();
|
||||||
if (auth === null) {
|
if (auth === null) {
|
||||||
return; // No auth selected
|
return; // No auth selected
|
||||||
|
@ -220,7 +218,7 @@ function goAuth(event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
settings.login = login;
|
settings.login = login;
|
||||||
doAuth(/*auth, */login, rsaPassword, authTypes[auth]);
|
doAuth(login, rsaPassword, authTypes[auth]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ======== Console ======== */
|
/* ======== Console ======== */
|
||||||
|
@ -259,17 +257,14 @@ function verifyLauncher(e) {
|
||||||
result.list.forEach(function(auth_type, i, arr) {
|
result.list.forEach(function(auth_type, i, arr) {
|
||||||
var serverAuth = new com.jfoenix.controls.JFXComboBox();
|
var serverAuth = new com.jfoenix.controls.JFXComboBox();
|
||||||
serverAuth.getStyleClass().add("authOptions");
|
serverAuth.getStyleClass().add("authOptions");
|
||||||
// add display name to items and add name with iter to variable authTypes
|
|
||||||
authOptions.getItems().add(auth_type.displayName);
|
authOptions.getItems().add(auth_type.displayName);
|
||||||
authTypes[auth_type.displayName] = auth_type.name;
|
authTypes[auth_type.displayName] = auth_type.name;
|
||||||
iter++;
|
iter++;
|
||||||
});
|
});
|
||||||
authOptions.getSelectionModel().select(0);
|
authOptions.getSelectionModel().select(0);
|
||||||
var sm = authOptions.getSelectionModel().selectedIndexProperty();
|
var sm = authOptions.getSelectionModel().selectedIndexProperty();
|
||||||
// add listener to authOptions select
|
|
||||||
sm.addListener(new javafx.beans.value.ChangeListener({
|
sm.addListener(new javafx.beans.value.ChangeListener({
|
||||||
changed: function (observableValue, oldSelection, newSelection) {
|
changed: function (observableValue, oldSelection, newSelection) {
|
||||||
// get auth name from authTypes
|
|
||||||
settings.auth = authTypes[authOptions.getSelectionModel().getSelectedItem()];
|
settings.auth = authTypes[authOptions.getSelectionModel().getSelectedItem()];
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
@ -423,8 +418,8 @@ var overlay = {
|
||||||
|
|
||||||
dimPane.setVisible(true);
|
dimPane.setVisible(true);
|
||||||
dimPane.toFront();
|
dimPane.toFront();
|
||||||
loginPaneLayout.setEffect(new javafx.scene.effect.GaussianBlur(55));
|
loginPaneLayout.setEffect(new javafx.scene.effect.GaussianBlur(10));
|
||||||
serverPaneLayout.setEffect(new javafx.scene.effect.GaussianBlur(55));
|
serverPaneLayout.setEffect(new javafx.scene.effect.GaussianBlur(10));
|
||||||
fade(dimPane, 0.0, 0.0, 1.0, function(event) {
|
fade(dimPane, 0.0, 0.0, 1.0, function(event) {
|
||||||
dimPane.requestFocus();
|
dimPane.requestFocus();
|
||||||
dimPane.getChildren().add(newOverlay);
|
dimPane.getChildren().add(newOverlay);
|
||||||
|
|
BIN
Launcher/runtime/dialog/images/downloader/blured.jpg
Normal file
BIN
Launcher/runtime/dialog/images/downloader/blured.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.8 KiB |
|
@ -17,7 +17,6 @@ var processing = {
|
||||||
setError: function(e) {
|
setError: function(e) {
|
||||||
LogHelper.error(e);
|
LogHelper.error(e);
|
||||||
processing.description.textProperty().unbind();
|
processing.description.textProperty().unbind();
|
||||||
//processing.errorImage.setImage(processing.errorImage);
|
|
||||||
processing.description.getStyleClass().add("error");
|
processing.description.getStyleClass().add("error");
|
||||||
processing.description.setText(e.toString());
|
processing.description.setText(e.toString());
|
||||||
},
|
},
|
||||||
|
@ -48,8 +47,6 @@ function offlineAuthRequest(login) {
|
||||||
Request.requestError("Имя пользователя некорректно");
|
Request.requestError("Имя пользователя некорректно");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return offline profile and random access token
|
|
||||||
return {
|
return {
|
||||||
pp: PlayerProfile.newOfflineProfile(login),
|
pp: PlayerProfile.newOfflineProfile(login),
|
||||||
accessToken: SecurityHelper.randomStringToken()
|
accessToken: SecurityHelper.randomStringToken()
|
||||||
|
@ -57,18 +54,15 @@ function offlineAuthRequest(login) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Export functions */
|
|
||||||
function makeLauncherRequest(callback) {
|
function makeLauncherRequest(callback) {
|
||||||
var task = settings.offline ? newTask(FunctionalBridge.offlineLauncherRequest) :
|
var task = settings.offline ? newTask(FunctionalBridge.offlineLauncherRequest) :
|
||||||
newRequestTask(new LauncherRequest());
|
newRequestTask(new LauncherRequest());
|
||||||
|
|
||||||
// Set task properties and start
|
|
||||||
processing.setTaskProperties(task, callback, function() {
|
processing.setTaskProperties(task, callback, function() {
|
||||||
if (settings.offline) {
|
if (settings.offline) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Repeat request, but in offline mode
|
|
||||||
settings.offline = true;
|
settings.offline = true;
|
||||||
overlay.swap(2500, processing.overlay, function() makeLauncherRequest(callback));
|
overlay.swap(2500, processing.overlay, function() makeLauncherRequest(callback));
|
||||||
}, false);
|
}, false);
|
||||||
|
@ -78,13 +72,11 @@ function makeLauncherRequest(callback) {
|
||||||
function makeProfilesRequest(callback) {
|
function makeProfilesRequest(callback) {
|
||||||
var task = newRequestTask(new ProfilesRequest());
|
var task = newRequestTask(new ProfilesRequest());
|
||||||
|
|
||||||
// Set task properties and start
|
|
||||||
processing.setTaskProperties(task, callback, function() {
|
processing.setTaskProperties(task, callback, function() {
|
||||||
if (settings.offline) {
|
if (settings.offline) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Repeat request, but in offline mode
|
|
||||||
settings.offline = true;
|
settings.offline = true;
|
||||||
overlay.swap(2500, processing.overlay, function() makeProfilesRequest(callback));
|
overlay.swap(2500, processing.overlay, function() makeProfilesRequest(callback));
|
||||||
}, false);
|
}, false);
|
||||||
|
@ -94,7 +86,6 @@ function makeProfilesRequest(callback) {
|
||||||
function makeAuthAvailabilityRequest(callback) {
|
function makeAuthAvailabilityRequest(callback) {
|
||||||
var task = newRequestTask(new GetAvailabilityAuthRequest());
|
var task = newRequestTask(new GetAvailabilityAuthRequest());
|
||||||
|
|
||||||
// Set task properties and start
|
|
||||||
processing.setTaskProperties(task, callback, function() {
|
processing.setTaskProperties(task, callback, function() {
|
||||||
if (settings.offline) {
|
if (settings.offline) {
|
||||||
return;
|
return;
|
||||||
|
@ -110,7 +101,6 @@ function makeAuthAvailabilityRequest(callback) {
|
||||||
function makeSetProfileRequest(profile, callback) {
|
function makeSetProfileRequest(profile, callback) {
|
||||||
var task = newRequestTask(new SetProfileRequest(profile));
|
var task = newRequestTask(new SetProfileRequest(profile));
|
||||||
|
|
||||||
// Set task properties and start
|
|
||||||
processing.setTaskProperties(task, callback, function() {
|
processing.setTaskProperties(task, callback, function() {
|
||||||
if (settings.offline) {
|
if (settings.offline) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#overlay {
|
#overlay {
|
||||||
-fx-background-color: transparent;
|
-fx-background-color: transparent;
|
||||||
-fx-background-size: cover;
|
-fx-background-size: cover;
|
||||||
-fx-background-image: url('../../images/background.jpg');
|
-fx-background-image: url('../../images/downloader/blured.jpg');
|
||||||
}
|
}
|
||||||
|
|
||||||
#overlay > #utitle {
|
#overlay > #utitle {
|
||||||
|
@ -20,7 +20,7 @@ #overlay > #description.error {
|
||||||
}
|
}
|
||||||
|
|
||||||
.downloadPane {
|
.downloadPane {
|
||||||
-fx-background-color: rgba(0, 0, 0, 0.3);
|
-fx-background-color: rgba(0, 0, 0, 0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Progress bar */
|
/* Progress bar */
|
||||||
|
|
|
@ -8,29 +8,27 @@
|
||||||
|
|
||||||
<!-- DrLeonardo Design -->
|
<!-- DrLeonardo Design -->
|
||||||
|
|
||||||
<Pane fx:id="overlay" prefHeight="450.0" prefWidth="693.0" xmlns="http://javafx.com/javafx/8.0.201"
|
<Pane fx:id="overlay" prefHeight="450.0" prefWidth="694.0" xmlns="http://javafx.com/javafx/8.0.201" xmlns:fx="http://javafx.com/fxml/1">
|
||||||
xmlns:fx="http://javafx.com/fxml/1">
|
<children>
|
||||||
<children>
|
<Pane prefHeight="450.0" prefWidth="694.0" styleClass="downloadPane">
|
||||||
<Pane prefHeight="450.0" prefWidth="693.0" styleClass="downloadPane">
|
<children>
|
||||||
<children>
|
<Label fx:id="utitle" alignment="CENTER" layoutX="100.0" layoutY="125.0" prefHeight="30.0" prefWidth="495.0" text="Загрузка обновления..." textFill="WHITE">
|
||||||
<Label fx:id="utitle" alignment="CENTER" layoutX="100.0" layoutY="125.0" prefHeight="30.0"
|
<font>
|
||||||
prefWidth="495.0" text="Загрузка обновления..." textFill="WHITE">
|
<Font name="System Bold" size="20.0" />
|
||||||
<font>
|
</font>
|
||||||
<Font name="System Bold" size="20.0"/>
|
</Label>
|
||||||
</font>
|
<JFXSpinner fx:id="progress" layoutX="98.0" layoutY="226.0" prefHeight="100.0" prefWidth="100.0" />
|
||||||
</Label>
|
<Label fx:id="description" layoutX="216.0" layoutY="226.0" prefHeight="100.0" prefWidth="380.0" text="..." textFill="WHITE">
|
||||||
<JFXSpinner fx:id="progress" layoutX="98.0" layoutY="226.0" prefHeight="100.0" prefWidth="100.0"/>
|
<font>
|
||||||
<Label fx:id="description" layoutX="216.0" layoutY="226.0" prefHeight="100.0" prefWidth="380.0"
|
<Font name="System Bold" size="16.0" />
|
||||||
text="..." textFill="WHITE">
|
</font>
|
||||||
<font>
|
</Label>
|
||||||
<Font name="System Bold" size="16.0"/>
|
</children>
|
||||||
</font>
|
</Pane>
|
||||||
</Label>
|
<Pane id="mask" layoutX="-1.0" opacity="0.0" prefHeight="450.0" prefWidth="694.0" visible="false" />
|
||||||
</children>
|
</children>
|
||||||
</Pane>
|
<stylesheets>
|
||||||
</children>
|
<URL value="@update.css" />
|
||||||
<stylesheets>
|
<URL value="@../../styles.css" />
|
||||||
<URL value="@update.css"/>
|
</stylesheets>
|
||||||
<URL value="@../../styles.css"/>
|
|
||||||
</stylesheets>
|
|
||||||
</Pane>
|
</Pane>
|
||||||
|
|
|
@ -4,6 +4,9 @@ var update = {
|
||||||
initOverlay: function() {
|
initOverlay: function() {
|
||||||
update.overlay = loadFXML("dialog/overlay/update/update.fxml");
|
update.overlay = loadFXML("dialog/overlay/update/update.fxml");
|
||||||
|
|
||||||
|
//var updateLayout = update.overlay.lookup("#overlay");
|
||||||
|
//serverPaneLayout = updateLayout;
|
||||||
|
|
||||||
update.title = update.overlay.lookup("#utitle");
|
update.title = update.overlay.lookup("#utitle");
|
||||||
update.description = update.overlay.lookup("#description");
|
update.description = update.overlay.lookup("#description");
|
||||||
update.progress = update.overlay.lookup("#progress");
|
update.progress = update.overlay.lookup("#progress");
|
||||||
|
|
|
@ -15,62 +15,51 @@
|
||||||
<!-- DrLeonardo Design -->
|
<!-- DrLeonardo Design -->
|
||||||
|
|
||||||
<Pane fx:id="loginPane" prefWidth="740.0" xmlns="http://javafx.com/javafx/8.0.201" xmlns:fx="http://javafx.com/fxml/1">
|
<Pane fx:id="loginPane" prefWidth="740.0" xmlns="http://javafx.com/javafx/8.0.201" xmlns:fx="http://javafx.com/fxml/1">
|
||||||
<children>
|
<children>
|
||||||
<Pane fx:id="layout" prefWidth="740.0">
|
<Pane fx:id="layout" prefWidth="740.0">
|
||||||
<children>
|
<children>
|
||||||
<Pane fx:id="authPane" layoutX="422.0" prefHeight="411.0" prefWidth="286.0" styleClass="loginPane">
|
<Pane fx:id="authPane" layoutX="424.0" prefHeight="411.0" prefWidth="286.0" styleClass="loginPane">
|
||||||
<children>
|
<children>
|
||||||
<Pane fx:id="logo" layoutX="72.0" layoutY="62.0" prefWidth="124.0" styleClass="logo">
|
<Pane fx:id="logo" layoutX="72.0" layoutY="62.0" prefWidth="124.0" styleClass="logo">
|
||||||
</Pane>
|
</Pane>
|
||||||
<JFXTextField id="login" alignment="CENTER" focusColor="#5fd97a" layoutX="34.0" layoutY="196.0"
|
<JFXTextField id="login" alignment="CENTER" focusColor="#5fd97a" layoutX="34.0" layoutY="196.0" promptText="Логин" unFocusColor="#dadada" />
|
||||||
promptText="Логин" unFocusColor="#dadada"/>
|
<JFXPasswordField id="password" alignment="CENTER" focusColor="#5fd97a" layoutX="34.0" layoutY="249.0" promptText="Пароль" unFocusColor="#dadada" />
|
||||||
<JFXPasswordField id="password" alignment="CENTER" focusColor="#5fd97a" layoutX="34.0"
|
<JFXButton id="goAuth" layoutX="34.0" layoutY="370.0" styleClass="auth" text="ВОЙТИ" />
|
||||||
layoutY="249.0" promptText="Пароль" unFocusColor="#dadada"/>
|
<JFXCheckBox id="rememberchb" fx:id="savePassword" checkedColor="#5fd97a" contentDisplay="CENTER" layoutX="63.0" layoutY="297.0" prefWidth="144.0" text="Сохранить пароль" textFill="#dadada" unCheckedColor="#909090" />
|
||||||
<JFXButton id="goAuth" layoutX="34.0" layoutY="370.0" styleClass="auth" text="ВОЙТИ"/>
|
<JFXComboBox id="authOptions" fx:id="authOptions" focusColor="#5fd97a" layoutX="34.0" layoutY="341.0" prefHeight="25.0" prefWidth="200.0" promptText="Способ авторизации" unFocusColor="#70666600">
|
||||||
<JFXCheckBox id="rememberchb" fx:id="savePassword" checkedColor="#5fd97a"
|
<styleClass>
|
||||||
contentDisplay="CENTER" layoutX="63.0" layoutY="297.0" prefWidth="144.0"
|
<String fx:value="combologin" />
|
||||||
text="Сохранить пароль" textFill="#dadada" unCheckedColor="#909090"/>
|
<String fx:value="combologin-popup" />
|
||||||
<JFXComboBox id="authOptions" fx:id="authOptions" focusColor="#5fd97a" layoutX="34.0"
|
</styleClass>
|
||||||
layoutY="341.0" prefHeight="25.0" prefWidth="200.0" promptText="Авторизация 1"
|
</JFXComboBox>
|
||||||
unFocusColor="#70666600">
|
<Hyperlink id="link" fx:id="link" layoutX="94.0" layoutY="422.0" prefHeight="19.0" prefWidth="81.0" textAlignment="CENTER" />
|
||||||
<styleClass>
|
</children>
|
||||||
<String fx:value="combologin"/>
|
</Pane>
|
||||||
<String fx:value="combologin-popup"/>
|
<JFXMasonryPane fx:id="news" prefHeight="432.0" prefWidth="423.0" styleClass="news" />
|
||||||
</styleClass>
|
</children>
|
||||||
</JFXComboBox>
|
</Pane>
|
||||||
<Hyperlink id="link" fx:id="link" layoutX="94.0" layoutY="422.0" prefHeight="19.0"
|
<Pane id="mask" opacity="0.0" prefHeight="450.0" prefWidth="694.0" visible="false" />
|
||||||
prefWidth="81.0" textAlignment="CENTER"/>
|
<Pane fx:id="bar" layoutX="694.0" prefHeight="425.0" prefWidth="43.0" styleClass="bar">
|
||||||
</children>
|
<children>
|
||||||
</Pane>
|
<JFXButton id="hide" alignment="CENTER" contentDisplay="CENTER" layoutY="45.0" ripplerFill="#646464" text="" textAlignment="CENTER">
|
||||||
<JFXMasonryPane fx:id="news" prefHeight="432.0" prefWidth="423.0" styleClass="news"/>
|
<graphic>
|
||||||
</children>
|
<MaterialDesignIconView fill="WHITE" glyphName="MINUS" size="30" textAlignment="CENTER" />
|
||||||
</Pane>
|
</graphic>
|
||||||
<Pane id="mask" opacity="0.0" prefHeight="425.0" prefWidth="694.0" visible="false"/>
|
</JFXButton>
|
||||||
<Pane fx:id="bar" layoutX="696.0" prefHeight="425.0" prefWidth="43.0" styleClass="bar">
|
<JFXButton id="close" alignment="CENTER" contentDisplay="CENTER" ripplerFill="#fb8c8c" text="" textAlignment="CENTER">
|
||||||
<children>
|
<graphic>
|
||||||
<JFXButton id="hide" alignment="CENTER" contentDisplay="CENTER" layoutY="45.0" ripplerFill="#646464"
|
<MaterialDesignIconView fill="WHITE" glyphName="CLOSE" size="30" textAlignment="CENTER" />
|
||||||
text="" textAlignment="CENTER">
|
</graphic>
|
||||||
<graphic>
|
</JFXButton>
|
||||||
<MaterialDesignIconView fill="WHITE" glyphName="MINUS" size="30" textAlignment="CENTER"/>
|
<JFXButton id="discord" alignment="CENTER" contentDisplay="CENTER" layoutY="370.0" ripplerFill="#646464" text="" textAlignment="CENTER">
|
||||||
</graphic>
|
<graphic>
|
||||||
</JFXButton>
|
<MaterialDesignIconView fill="#5fd97a" glyphName="MESSAGE_TEXT" size="20" textAlignment="CENTER" />
|
||||||
<JFXButton id="close" alignment="CENTER" contentDisplay="CENTER" ripplerFill="#fb8c8c" text=""
|
</graphic>
|
||||||
textAlignment="CENTER">
|
</JFXButton>
|
||||||
<graphic>
|
</children>
|
||||||
<MaterialDesignIconView fill="WHITE" glyphName="CLOSE" size="30" textAlignment="CENTER"/>
|
</Pane>
|
||||||
</graphic>
|
</children>
|
||||||
</JFXButton>
|
<stylesheets>
|
||||||
<JFXButton id="discord" alignment="CENTER" contentDisplay="CENTER" layoutY="370.0" ripplerFill="#646464"
|
<URL value="@../../styles.css" />
|
||||||
text="" textAlignment="CENTER">
|
</stylesheets>
|
||||||
<graphic>
|
|
||||||
<MaterialDesignIconView fill="#5fd97a" glyphName="MESSAGE_TEXT" size="20"
|
|
||||||
textAlignment="CENTER"/>
|
|
||||||
</graphic>
|
|
||||||
</JFXButton>
|
|
||||||
</children>
|
|
||||||
</Pane>
|
|
||||||
</children>
|
|
||||||
<stylesheets>
|
|
||||||
<URL value="@../../styles.css"/>
|
|
||||||
</stylesheets>
|
|
||||||
</Pane>
|
</Pane>
|
||||||
|
|
|
@ -13,127 +13,98 @@
|
||||||
|
|
||||||
<!-- DrLeonardo Design -->
|
<!-- DrLeonardo Design -->
|
||||||
|
|
||||||
<Pane fx:id="serverPaneLayout" maxHeight="-1.0" maxWidth="-1.0" prefWidth="740.0" visible="true"
|
<Pane fx:id="serverPaneLayout" maxHeight="-1.0" maxWidth="-1.0" prefWidth="740.0" visible="true" xmlns="http://javafx.com/javafx/8.0.201" xmlns:fx="http://javafx.com/fxml/1">
|
||||||
xmlns="http://javafx.com/javafx/8.0.201" xmlns:fx="http://javafx.com/fxml/1">
|
|
||||||
<children>
|
<children>
|
||||||
<Pane fx:id="layout" maxHeight="-1.0" maxWidth="-1.0" prefWidth="740.0" visible="true"
|
<Pane fx:id="layout" maxHeight="-1.0" maxWidth="-1.0" prefWidth="740.0" visible="true" xmlns="http://javafx.com/javafx/8.0.201" xmlns:fx="http://javafx.com/fxml/1">
|
||||||
xmlns="http://javafx.com/javafx/8.0.201" xmlns:fx="http://javafx.com/fxml/1">
|
|
||||||
<children>
|
<children>
|
||||||
<Pane id="serverPane" prefHeight="450.0" prefWidth="693.0">
|
<Pane id="serverPane" prefHeight="450.0" prefWidth="694.0">
|
||||||
<children>
|
<children>
|
||||||
<ScrollPane id="serverlist" hbarPolicy="NEVER" layoutX="1.0" prefHeight="450.0"
|
<ScrollPane id="serverlist" hbarPolicy="NEVER" layoutX="1.0" prefHeight="450.0" prefWidth="307.0" visible="true">
|
||||||
prefWidth="307.0" visible="true">
|
|
||||||
<content>
|
<content>
|
||||||
<FlowPane focusTraversable="false" prefHeight="446.0" prefWidth="306.0"
|
<FlowPane focusTraversable="false" prefHeight="446.0" prefWidth="306.0" prefWrapLength="0.0" rowValignment="TOP" vgap="10.0" visible="true">
|
||||||
prefWrapLength="0.0" rowValignment="TOP" vgap="10.0" visible="true">
|
|
||||||
<JFXButton id="servercontainer" ripplerFill="#ffffff80" text="">
|
<JFXButton id="servercontainer" ripplerFill="#ffffff80" text="">
|
||||||
<FlowPane.margin>
|
<FlowPane.margin>
|
||||||
<Insets bottom="10.0"/>
|
<Insets bottom="10.0" />
|
||||||
</FlowPane.margin>
|
</FlowPane.margin></JFXButton>
|
||||||
</JFXButton>
|
|
||||||
<padding>
|
<padding>
|
||||||
<Insets left="10.0" top="10.0"/>
|
<Insets left="10.0" top="10.0" />
|
||||||
</padding>
|
</padding>
|
||||||
</FlowPane>
|
</FlowPane>
|
||||||
</content>
|
</content>
|
||||||
</ScrollPane>
|
</ScrollPane>
|
||||||
<Pane id="serverentrance" layoutX="306.0" prefHeight="425.0" prefWidth="388.0"
|
<Pane id="serverentrance" layoutX="308.0" prefHeight="425.0" prefWidth="388.0" styleClass="serverentrance">
|
||||||
styleClass="serverentrance">
|
|
||||||
<children>
|
<children>
|
||||||
<ScrollPane id="serverinfo" hbarPolicy="NEVER" layoutX="4.0" layoutY="53.0"
|
<ScrollPane id="serverinfo" hbarPolicy="NEVER" layoutX="4.0" layoutY="53.0" pannable="true" prefHeight="322.0" prefWidth="381.0" visible="true">
|
||||||
pannable="true" prefHeight="322.0" prefWidth="381.0" visible="true">
|
|
||||||
<content>
|
<content>
|
||||||
<FlowPane id="" focusTraversable="false" orientation="HORIZONTAL"
|
<FlowPane id="" focusTraversable="false" orientation="HORIZONTAL" prefHeight="310.0" prefWidth="369.0" rowValignment="TOP" visible="true">
|
||||||
prefHeight="310.0" prefWidth="369.0" rowValignment="TOP"
|
|
||||||
visible="true">
|
|
||||||
<padding>
|
<padding>
|
||||||
<Insets bottom="10.0" left="15.0" top="7.0"/>
|
<Insets bottom="10.0" left="15.0" top="7.0" />
|
||||||
</padding>
|
</padding>
|
||||||
<children>
|
<children>
|
||||||
<Label id="serverDescription" alignment="TOP_LEFT" contentDisplay="LEFT"
|
<Label id="serverDescription" alignment="TOP_LEFT" contentDisplay="LEFT" nodeOrientation="LEFT_TO_RIGHT" prefHeight="274.0" prefWidth="349.0" text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla convallis magna tellus, in bibendum tortor dignissim non. Phasellus vel tincidunt nulla, eu convallis ligula. Suspendisse ut diam vestibulum, tincidunt neque ut, posuere risus. Pellentesque posuere molestie eros, quis laoreet ante ornare quis. Morbi eu tortor fermentum, iaculis risus sit amet, fringilla augue. Aenean nulla purus, rutrum non sapien et, convallis tincidunt purus. Vivamus a eros pulvinar, dignissim leo lacinia, sodales nulla. Aliquam tortor augue, cursus a rutrum viverra, consequat non tellus. Donec porta nisl sed quam dictum commodo. Sed et vulputate dolor. Morbi ultrices justo vitae convallis semper. Donec sodales velit vel velit faucibus, et scelerisque felis finibus. Sed rutrum lacinia mauris, porta cursus mauris tempor eu. Duis turpis nulla, dictum vitae commodo rhoncus, pretium in turpis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos." textAlignment="JUSTIFY" textFill="#141414" wrapText="true" />
|
||||||
nodeOrientation="LEFT_TO_RIGHT" prefHeight="274.0"
|
|
||||||
prefWidth="349.0"
|
|
||||||
text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla convallis magna tellus, in bibendum tortor dignissim non. Phasellus vel tincidunt nulla, eu convallis ligula. Suspendisse ut diam vestibulum, tincidunt neque ut, posuere risus. Pellentesque posuere molestie eros, quis laoreet ante ornare quis. Morbi eu tortor fermentum, iaculis risus sit amet, fringilla augue. Aenean nulla purus, rutrum non sapien et, convallis tincidunt purus. Vivamus a eros pulvinar, dignissim leo lacinia, sodales nulla. Aliquam tortor augue, cursus a rutrum viverra, consequat non tellus. Donec porta nisl sed quam dictum commodo. Sed et vulputate dolor. Morbi ultrices justo vitae convallis semper. Donec sodales velit vel velit faucibus, et scelerisque felis finibus. Sed rutrum lacinia mauris, porta cursus mauris tempor eu. Duis turpis nulla, dictum vitae commodo rhoncus, pretium in turpis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos."
|
|
||||||
textAlignment="JUSTIFY" textFill="#141414" wrapText="true"/>
|
|
||||||
</children>
|
</children>
|
||||||
</FlowPane>
|
</FlowPane>
|
||||||
</content>
|
</content>
|
||||||
</ScrollPane>
|
</ScrollPane>
|
||||||
<JFXButton id="clientLaunch" layoutX="19.0" layoutY="380.0" prefHeight="51.0"
|
<JFXButton id="clientLaunch" layoutX="19.0" layoutY="380.0" prefHeight="51.0" prefWidth="285.0" styleClass="clientLaunch" text="ИГРАТЬ">
|
||||||
prefWidth="285.0" styleClass="clientLaunch" text="ИГРАТЬ">
|
|
||||||
<font>
|
<font>
|
||||||
<Font size="22.0"/>
|
<Font size="22.0" />
|
||||||
</font>
|
</font>
|
||||||
</JFXButton>
|
</JFXButton>
|
||||||
<JFXButton id="clientSettings" alignment="CENTER" centerShape="false"
|
<JFXButton id="clientSettings" alignment="CENTER" centerShape="false" contentDisplay="CENTER" layoutX="305.0" layoutY="380.0" prefHeight="51.0" prefWidth="60.0" ripplerFill="#84da96" styleClass="clientSettings" text="" textAlignment="CENTER">
|
||||||
contentDisplay="CENTER" layoutX="305.0" layoutY="380.0" prefHeight="51.0"
|
|
||||||
prefWidth="60.0" ripplerFill="#84da96" styleClass="clientSettings" text=""
|
|
||||||
textAlignment="CENTER">
|
|
||||||
<graphic>
|
<graphic>
|
||||||
<FontAwesomeIconView fill="WHITE" glyphName="SLIDERS" size="30.0"/>
|
<FontAwesomeIconView fill="WHITE" glyphName="SLIDERS" size="30.0" />
|
||||||
</graphic>
|
</graphic></JFXButton>
|
||||||
</JFXButton>
|
<Label id="serverStatus" alignment="TOP_RIGHT" contentDisplay="RIGHT" layoutX="165.0" layoutY="12.0" prefHeight="25.0" prefWidth="97.0" text="12/100" textAlignment="RIGHT" textFill="WHITE">
|
||||||
<Label id="serverStatus" alignment="TOP_RIGHT" contentDisplay="RIGHT" layoutX="165.0"
|
|
||||||
layoutY="12.0" prefHeight="25.0" prefWidth="97.0" text="12/100"
|
|
||||||
textAlignment="RIGHT" textFill="WHITE">
|
|
||||||
<font>
|
<font>
|
||||||
<Font name="System Bold" size="16.0"/>
|
<Font name="System Bold" size="16.0" />
|
||||||
</font>
|
</font>
|
||||||
</Label>
|
</Label>
|
||||||
<Label id="serverLabel" layoutX="20.0" layoutY="11.0" prefHeight="27.0"
|
<Label id="serverLabel" layoutX="20.0" layoutY="11.0" prefHeight="27.0" prefWidth="203.0" text="СЕРВЕР">
|
||||||
prefWidth="203.0" text="СЕРВЕР">
|
|
||||||
<font>
|
<font>
|
||||||
<Font name="System Bold" size="18.0"/>
|
<Font name="System Bold" size="18.0" />
|
||||||
</font>
|
</font>
|
||||||
</Label>
|
</Label>
|
||||||
<JFXButton id="logout" alignment="CENTER" contentDisplay="CENTER" layoutX="295.0"
|
<JFXButton id="logout" alignment="CENTER" contentDisplay="CENTER" layoutX="295.0" layoutY="12.0" prefHeight="25.0" prefWidth="81.0" ripplerFill="#61616100" text="Выйти" textAlignment="CENTER" />
|
||||||
layoutY="12.0" prefHeight="25.0" prefWidth="81.0" ripplerFill="#61616100"
|
|
||||||
text="Выйти" textAlignment="CENTER"/>
|
|
||||||
</children>
|
</children>
|
||||||
</Pane>
|
</Pane>
|
||||||
</children>
|
</children>
|
||||||
</Pane>
|
</Pane>
|
||||||
</children>
|
</children>
|
||||||
</Pane>
|
</Pane>
|
||||||
<Pane fx:id="bar" layoutX="696.0" prefHeight="425.0" prefWidth="43.0" styleClass="bar">
|
<Pane fx:id="bar" layoutX="694.0" prefHeight="425.0" prefWidth="43.0" styleClass="bar">
|
||||||
<children>
|
<children>
|
||||||
<JFXButton id="hide" alignment="CENTER" contentDisplay="CENTER" layoutY="45.0" ripplerFill="#646464"
|
<JFXButton id="hide" alignment="CENTER" contentDisplay="CENTER" layoutY="45.0" ripplerFill="#646464" text="" textAlignment="CENTER">
|
||||||
text="" textAlignment="CENTER">
|
|
||||||
<graphic>
|
<graphic>
|
||||||
<MaterialDesignIconView fill="WHITE" glyphName="MINUS" size="30" textAlignment="CENTER"/>
|
<MaterialDesignIconView fill="WHITE" glyphName="MINUS" size="30" textAlignment="CENTER" />
|
||||||
</graphic>
|
</graphic>
|
||||||
</JFXButton>
|
</JFXButton>
|
||||||
<JFXButton id="close" alignment="CENTER" contentDisplay="CENTER" ripplerFill="#fb8c8c" text=""
|
<JFXButton id="close" alignment="CENTER" contentDisplay="CENTER" ripplerFill="#fb8c8c" text="" textAlignment="CENTER">
|
||||||
textAlignment="CENTER">
|
|
||||||
<graphic>
|
<graphic>
|
||||||
<MaterialDesignIconView fill="WHITE" glyphName="CLOSE" size="30" textAlignment="CENTER"/>
|
<MaterialDesignIconView fill="WHITE" glyphName="CLOSE" size="30" textAlignment="CENTER" />
|
||||||
</graphic>
|
</graphic>
|
||||||
</JFXButton>
|
</JFXButton>
|
||||||
<JFXButton id="discord" alignment="CENTER" contentDisplay="CENTER" layoutY="380.0" ripplerFill="#646464"
|
<JFXButton id="discord" alignment="CENTER" contentDisplay="CENTER" layoutY="380.0" ripplerFill="#646464" text="" textAlignment="CENTER">
|
||||||
text="" textAlignment="CENTER">
|
|
||||||
<graphic>
|
<graphic>
|
||||||
<MaterialDesignIconView fill="#5fd97a" glyphName="MESSAGE_TEXT" size="20" smooth="false"
|
<MaterialDesignIconView fill="#5fd97a" glyphName="MESSAGE_TEXT" size="20" smooth="false" textAlignment="CENTER" />
|
||||||
textAlignment="CENTER"/>
|
|
||||||
</graphic>
|
</graphic>
|
||||||
</JFXButton>
|
</JFXButton>
|
||||||
<JFXButton id="settings" alignment="CENTER" contentDisplay="CENTER" layoutY="90.0" ripplerFill="#646464"
|
<JFXButton id="settings" alignment="CENTER" contentDisplay="CENTER" layoutY="90.0" ripplerFill="#646464" text="" textAlignment="CENTER">
|
||||||
text="" textAlignment="CENTER">
|
|
||||||
<graphic>
|
<graphic>
|
||||||
<MaterialDesignIconView fill="WHITE" glyphName="SETTINGS" size="20" textAlignment="CENTER"/>
|
<MaterialDesignIconView fill="WHITE" glyphName="SETTINGS" size="20" textAlignment="CENTER" />
|
||||||
</graphic>
|
</graphic>
|
||||||
</JFXButton>
|
</JFXButton>
|
||||||
<JFXButton id="goConsole" alignment="CENTER" contentDisplay="CENTER" layoutY="138.0"
|
<JFXButton id="goConsole" alignment="CENTER" contentDisplay="CENTER" layoutY="138.0" ripplerFill="#646464" text="" textAlignment="CENTER">
|
||||||
ripplerFill="#646464" text="" textAlignment="CENTER">
|
|
||||||
<graphic>
|
<graphic>
|
||||||
<MaterialDesignIconView fill="WHITE" glyphName="CONSOLE" size="20" textAlignment="CENTER"/>
|
<MaterialDesignIconView fill="WHITE" glyphName="CONSOLE" size="20" textAlignment="CENTER" />
|
||||||
</graphic>
|
</graphic>
|
||||||
</JFXButton>
|
</JFXButton>
|
||||||
</children>
|
</children>
|
||||||
</Pane>
|
</Pane>
|
||||||
<Pane id="mask" opacity="0.0" prefHeight="425.0" prefWidth="694.0" visible="false"/>
|
<Pane id="mask" opacity="0.0" prefHeight="450.0" prefWidth="694.0" visible="false" />
|
||||||
</children>
|
</children>
|
||||||
<stylesheets>
|
<stylesheets>
|
||||||
<URL value="@../../styles.css"/>
|
<URL value="@../../styles.css" />
|
||||||
<URL value="@../../servers.css"/>
|
<URL value="@../../servers.css" />
|
||||||
</stylesheets>
|
</stylesheets>
|
||||||
</Pane>
|
</Pane>
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
<?import com.jfoenix.controls.JFXButton?>
|
<?import com.jfoenix.controls.JFXButton?>
|
||||||
<?import com.jfoenix.controls.JFXToggleButton?>
|
|
||||||
<?import de.jensd.fx.glyphs.materialdesignicons.MaterialDesignIconView?>
|
<?import de.jensd.fx.glyphs.materialdesignicons.MaterialDesignIconView?>
|
||||||
<?import java.net.URL?>
|
<?import java.net.URL?>
|
||||||
<?import javafx.geometry.Insets?>
|
<?import javafx.geometry.Insets?>
|
||||||
|
@ -9,59 +8,55 @@
|
||||||
<?import javafx.scene.layout.Pane?>
|
<?import javafx.scene.layout.Pane?>
|
||||||
<?import javafx.scene.layout.VBox?>
|
<?import javafx.scene.layout.VBox?>
|
||||||
<?import javafx.scene.shape.Line?>
|
<?import javafx.scene.shape.Line?>
|
||||||
|
<?import javafx.scene.text.Font?>
|
||||||
|
<?import javafx.scene.text.Text?>
|
||||||
|
|
||||||
<!-- DrLeonardo Design -->
|
<!-- DrLeonardo Design -->
|
||||||
|
|
||||||
<Pane fx:id="background" prefHeight="450.0" prefWidth="738.0" xmlns="http://javafx.com/javafx/8.0.201"
|
<Pane fx:id="background" prefHeight="450.0" prefWidth="740.0" xmlns="http://javafx.com/javafx/8.0.201" xmlns:fx="http://javafx.com/fxml/1">
|
||||||
xmlns:fx="http://javafx.com/fxml/1">
|
<children>
|
||||||
<children>
|
<Pane id="optionsPane" prefHeight="450.0" prefWidth="692.0" styleClass="optionsPane">
|
||||||
<Pane id="optionsPane" prefHeight="450.0" prefWidth="692.0" styleClass="optionsPane">
|
<children>
|
||||||
<children>
|
<Line endX="595.0" layoutX="100.0" layoutY="46.0" startX="-100.0" stroke="#5b3636" styleClass="lineHead" />
|
||||||
<JFXToggleButton fx:id="presset" layoutX="30.0" layoutY="10.0" opacity="0.21" styleClass="pressetLight"
|
<ScrollPane id="modlist" layoutY="46.0" prefHeight="402.0" prefWidth="693.0">
|
||||||
text="Presset 1"/>
|
<content>
|
||||||
<JFXToggleButton fx:id="presset" layoutX="287.0" layoutY="10.0" opacity="0.21"
|
<VBox prefHeight="397.0" prefWidth="678.0">
|
||||||
styleClass="pressetMedium" text="Presset 2"/>
|
<children>
|
||||||
<JFXToggleButton fx:id="isPresset" layoutX="528.0" layoutY="10.0" opacity="0.21" prefHeight="58.0"
|
</children>
|
||||||
prefWidth="134.0" styleClass="pressetHigh" text="Presset 3" wrapText="true"/>
|
<padding>
|
||||||
<Line endX="595.0" layoutX="100.0" layoutY="80.0" startX="-100.0" stroke="#5b3636"
|
<Insets left="10.0" top="8.0" />
|
||||||
styleClass="lineHead"/>
|
</padding>
|
||||||
<ScrollPane id="modlist" layoutY="84.0" prefHeight="364.0" prefWidth="693.0">
|
</VBox>
|
||||||
<content>
|
</content>
|
||||||
<VBox prefHeight="360.0" prefWidth="678.0">
|
</ScrollPane>
|
||||||
<children>
|
<Text fill="#393939" layoutX="15.0" layoutY="28.0" strokeType="OUTSIDE" strokeWidth="0.0" text="ОПЦИОНАЛЬНЫЕ МОДИФИКАЦИИ" wrappingWidth="265.904296875">
|
||||||
</children>
|
<font>
|
||||||
<padding>
|
<Font name="System Bold" size="13.0" />
|
||||||
<Insets left="10.0" top="8.0"/>
|
</font>
|
||||||
</padding>
|
</Text>
|
||||||
</VBox>
|
</children>
|
||||||
</content>
|
</Pane>
|
||||||
</ScrollPane>
|
<Pane fx:id="bar" layoutX="694.0" prefHeight="425.0" prefWidth="43.0" styleClass="bar">
|
||||||
</children>
|
<children>
|
||||||
</Pane>
|
<JFXButton id="hide" alignment="CENTER" contentDisplay="CENTER" layoutY="45.0" ripplerFill="#646464" text="" textAlignment="CENTER">
|
||||||
<Pane fx:id="bar" layoutX="692.0" prefHeight="425.0" prefWidth="43.0" styleClass="bar">
|
<graphic>
|
||||||
<children>
|
<MaterialDesignIconView fill="WHITE" glyphName="MINUS" size="30" textAlignment="CENTER" />
|
||||||
<JFXButton id="hide" alignment="CENTER" contentDisplay="CENTER" layoutY="45.0" ripplerFill="#646464"
|
</graphic>
|
||||||
text="" textAlignment="CENTER">
|
</JFXButton>
|
||||||
<graphic>
|
<JFXButton id="close" alignment="CENTER" contentDisplay="CENTER" ripplerFill="#fb8c8c" text="" textAlignment="CENTER">
|
||||||
<MaterialDesignIconView fill="WHITE" glyphName="MINUS" size="30" textAlignment="CENTER"/>
|
<graphic>
|
||||||
</graphic>
|
<MaterialDesignIconView fill="WHITE" glyphName="CLOSE" size="30" textAlignment="CENTER" />
|
||||||
</JFXButton>
|
</graphic>
|
||||||
<JFXButton id="close" alignment="CENTER" contentDisplay="CENTER" ripplerFill="#fb8c8c" text=""
|
</JFXButton>
|
||||||
textAlignment="CENTER">
|
<JFXButton id="back" alignment="CENTER" contentDisplay="CENTER" layoutY="405.0" ripplerFill="#646464" text="" textAlignment="CENTER">
|
||||||
<graphic>
|
<graphic>
|
||||||
<MaterialDesignIconView fill="WHITE" glyphName="CLOSE" size="30" textAlignment="CENTER"/>
|
<MaterialDesignIconView fill="WHITE" glyphName="CHEVRON_LEFT" size="30" textAlignment="CENTER" />
|
||||||
</graphic>
|
</graphic>
|
||||||
</JFXButton>
|
</JFXButton>
|
||||||
<JFXButton id="back" alignment="CENTER" contentDisplay="CENTER" layoutY="405.0" ripplerFill="#646464"
|
</children>
|
||||||
text="" textAlignment="CENTER">
|
</Pane>
|
||||||
<graphic>
|
</children>
|
||||||
<MaterialDesignIconView fill="WHITE" glyphName="CHEVRON_LEFT" size="30" textAlignment="CENTER"/>
|
<stylesheets>
|
||||||
</graphic>
|
<URL value="@../../styles.css" />
|
||||||
</JFXButton>
|
</stylesheets>
|
||||||
</children>
|
|
||||||
</Pane>
|
|
||||||
</children>
|
|
||||||
<stylesheets>
|
|
||||||
<URL value="@../../styles.css"/>
|
|
||||||
</stylesheets>
|
|
||||||
</Pane>
|
</Pane>
|
||||||
|
|
|
@ -34,8 +34,6 @@ #serverStatus{
|
||||||
/* Mask */
|
/* Mask */
|
||||||
#mask {
|
#mask {
|
||||||
-fx-effect: DropShadow( gaussian , rgba(255,255,255,0.5) , 0,0,0,1 );
|
-fx-effect: DropShadow( gaussian , rgba(255,255,255,0.5) , 0,0,0,1 );
|
||||||
-fx-pref-width: 692px;
|
|
||||||
-fx-pref-height: 450px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Errors **/
|
/** Errors **/
|
||||||
|
@ -194,7 +192,7 @@ .combologin-popup .list-view {
|
||||||
|
|
||||||
.combologin .list-cell:filled:selected .text,
|
.combologin .list-cell:filled:selected .text,
|
||||||
.combologin .list-cell:filled:selected .text {
|
.combologin .list-cell:filled:selected .text {
|
||||||
-fx-fill: #909090;
|
-fx-fill: #323232;
|
||||||
}
|
}
|
||||||
|
|
||||||
.combologin .arrow,
|
.combologin .arrow,
|
||||||
|
@ -211,13 +209,13 @@ .combologin-popup .list-view .list-cell:filled:selected, .combologin-popup .list
|
||||||
{
|
{
|
||||||
-fx-background: -fx-accent;
|
-fx-background: -fx-accent;
|
||||||
-fx-background-color: -fx-selection-bar;
|
-fx-background-color: -fx-selection-bar;
|
||||||
-fx-text-fill: -fx-selection-bar-text;
|
-fx-text-fill: #909090;
|
||||||
}
|
}
|
||||||
|
|
||||||
.combologin-popup .list-view .list-cell:filled:hover
|
.combologin-popup .list-view .list-cell:filled:hover
|
||||||
{
|
{
|
||||||
-fx-background-color: white;
|
-fx-background-color: white;
|
||||||
-fx-text-fill: -fx-text-inner-color;
|
-fx-text-fill: #909090;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** web**/
|
/** web**/
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
import ru.gravit.launcher.client.ClientModuleManager;
|
import ru.gravit.launcher.client.ClientModuleManager;
|
||||||
import ru.gravit.launcher.client.DirBridge;
|
import ru.gravit.launcher.client.DirBridge;
|
||||||
import ru.gravit.launcher.client.FunctionalBridge;
|
import ru.gravit.launcher.client.FunctionalBridge;
|
||||||
|
import ru.gravit.launcher.client.LauncherUpdateController;
|
||||||
import ru.gravit.launcher.guard.LauncherGuardManager;
|
import ru.gravit.launcher.guard.LauncherGuardManager;
|
||||||
import ru.gravit.launcher.gui.JSRuntimeProvider;
|
import ru.gravit.launcher.gui.JSRuntimeProvider;
|
||||||
import ru.gravit.launcher.gui.RuntimeProvider;
|
import ru.gravit.launcher.gui.RuntimeProvider;
|
||||||
|
@ -11,6 +12,7 @@
|
||||||
import ru.gravit.launcher.request.Request;
|
import ru.gravit.launcher.request.Request;
|
||||||
import ru.gravit.launcher.request.RequestException;
|
import ru.gravit.launcher.request.RequestException;
|
||||||
import ru.gravit.launcher.request.auth.RestoreSessionRequest;
|
import ru.gravit.launcher.request.auth.RestoreSessionRequest;
|
||||||
|
import ru.gravit.launcher.request.update.UpdateRequest;
|
||||||
import ru.gravit.launcher.request.websockets.StandartClientWebSocketService;
|
import ru.gravit.launcher.request.websockets.StandartClientWebSocketService;
|
||||||
import ru.gravit.utils.helper.CommonHelper;
|
import ru.gravit.utils.helper.CommonHelper;
|
||||||
import ru.gravit.utils.helper.EnvHelper;
|
import ru.gravit.utils.helper.EnvHelper;
|
||||||
|
@ -95,6 +97,7 @@ public void start(String... args) throws Throwable {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
LauncherGuardManager.initGuard(false);
|
LauncherGuardManager.initGuard(false);
|
||||||
|
UpdateRequest.setController(new LauncherUpdateController());
|
||||||
Objects.requireNonNull(args, "args");
|
Objects.requireNonNull(args, "args");
|
||||||
if (started.getAndSet(true))
|
if (started.getAndSet(true))
|
||||||
throw new IllegalStateException("Launcher has been already started");
|
throw new IllegalStateException("Launcher has been already started");
|
||||||
|
|
|
@ -37,6 +37,10 @@ public class NewLauncherSettings {
|
||||||
public List<ClientProfile> lastProfiles = new LinkedList<>();
|
public List<ClientProfile> lastProfiles = new LinkedList<>();
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
public Map<String, UserSettings> userSettings = new HashMap<>();
|
public Map<String, UserSettings> userSettings = new HashMap<>();
|
||||||
|
@LauncherAPI
|
||||||
|
public boolean featureStore;
|
||||||
|
@LauncherAPI
|
||||||
|
public String consoleUnlockKey;
|
||||||
|
|
||||||
public static class HashedStoreEntry {
|
public static class HashedStoreEntry {
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
|
@ -45,6 +49,8 @@ public static class HashedStoreEntry {
|
||||||
public String name;
|
public String name;
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
public String fullPath;
|
public String fullPath;
|
||||||
|
@LauncherAPI
|
||||||
|
public transient boolean needSave = false;
|
||||||
|
|
||||||
public HashedStoreEntry(HashedDir hdir, String name, String fullPath) {
|
public HashedStoreEntry(HashedDir hdir, String name, String fullPath) {
|
||||||
this.hdir = hdir;
|
this.hdir = hdir;
|
||||||
|
@ -59,9 +65,9 @@ public HashedStoreEntry(HashedDir hdir, String name, String fullPath) {
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
public void putHDir(String name, Path path, HashedDir dir) {
|
public void putHDir(String name, Path path, HashedDir dir) {
|
||||||
String fullPath = path.toAbsolutePath().toString();
|
String fullPath = path.toAbsolutePath().toString();
|
||||||
for (HashedStoreEntry e : lastHDirs) {
|
lastHDirs.removeIf((e) -> e.fullPath.equals(fullPath) && e.name.equals(name));
|
||||||
if (e.fullPath.equals(fullPath) && e.name.equals(name)) return;
|
HashedStoreEntry e = new HashedStoreEntry(dir, name, fullPath);
|
||||||
}
|
e.needSave = true;
|
||||||
lastHDirs.add(new HashedStoreEntry(dir, name, fullPath));
|
lastHDirs.add(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,139 @@
|
||||||
|
package ru.gravit.launcher.client;
|
||||||
|
|
||||||
|
import ru.gravit.launcher.NewLauncherSettings;
|
||||||
|
import ru.gravit.launcher.downloader.ListDownloader;
|
||||||
|
import ru.gravit.launcher.events.request.UpdateRequestEvent;
|
||||||
|
import ru.gravit.launcher.hasher.HashedDir;
|
||||||
|
import ru.gravit.launcher.hasher.HashedEntry;
|
||||||
|
import ru.gravit.launcher.hasher.HashedFile;
|
||||||
|
import ru.gravit.launcher.managers.SettingsManager;
|
||||||
|
import ru.gravit.launcher.request.update.UpdateRequest;
|
||||||
|
import ru.gravit.utils.helper.IOHelper;
|
||||||
|
import ru.gravit.utils.helper.LogHelper;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
|
public class LauncherUpdateController implements UpdateRequest.UpdateController {
|
||||||
|
@Override
|
||||||
|
public void preUpdate(UpdateRequest request, UpdateRequestEvent e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void preDiff(UpdateRequest request, UpdateRequestEvent e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void postDiff(UpdateRequest request, UpdateRequestEvent e, HashedDir.Diff diff) throws IOException {
|
||||||
|
if(e.zip) return;
|
||||||
|
if(SettingsManager.settings.featureStore)
|
||||||
|
{
|
||||||
|
LogHelper.info("Enabled HStore feature. Find");
|
||||||
|
AtomicReference<NewLauncherSettings.HashedStoreEntry> lastEn = new AtomicReference<>(null);
|
||||||
|
ArrayList<String> removed = new ArrayList<>();
|
||||||
|
diff.mismatch.walk(File.separator, (path, name, entry) -> {
|
||||||
|
if(entry.getType() == HashedEntry.Type.DIR) {
|
||||||
|
Files.createDirectories(request.getDir().resolve(path));
|
||||||
|
return HashedDir.WalkAction.CONTINUE;
|
||||||
|
}
|
||||||
|
HashedFile file = (HashedFile) entry;
|
||||||
|
//Первый экспериментальный способ - честно обходим все возможные Store
|
||||||
|
Path ret = null;
|
||||||
|
if(lastEn.get() == null)
|
||||||
|
{
|
||||||
|
for(NewLauncherSettings.HashedStoreEntry en : SettingsManager.settings.lastHDirs)
|
||||||
|
{
|
||||||
|
ret = tryFind(en, file);
|
||||||
|
if(ret != null) {
|
||||||
|
lastEn.set(en);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = tryFind(lastEn.get(), file);
|
||||||
|
}
|
||||||
|
if(ret == null)
|
||||||
|
{
|
||||||
|
for(NewLauncherSettings.HashedStoreEntry en : SettingsManager.settings.lastHDirs)
|
||||||
|
{
|
||||||
|
ret = tryFind(en, file);
|
||||||
|
if(ret != null) {
|
||||||
|
lastEn.set(en);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(ret != null)
|
||||||
|
{
|
||||||
|
//Еще раз проверим корректность хеша
|
||||||
|
//Возможно эта проверка избыточна
|
||||||
|
//if(file.isSame(ret, true))
|
||||||
|
{
|
||||||
|
Path source = request.getDir().resolve(path);
|
||||||
|
LogHelper.debug("Copy file %s to %s", ret.toAbsolutePath().toString(), source.toAbsolutePath().toString());
|
||||||
|
//Let's go!
|
||||||
|
Files.copy(ret, source);
|
||||||
|
try(InputStream input = IOHelper.newInput(ret))
|
||||||
|
{
|
||||||
|
IOHelper.transfer(input, source);
|
||||||
|
}
|
||||||
|
entry.flag = true;
|
||||||
|
//removed.add(path.replace('\\', '/'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return HashedDir.WalkAction.CONTINUE;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public Path tryFind(NewLauncherSettings.HashedStoreEntry en, HashedFile file) throws IOException
|
||||||
|
{
|
||||||
|
AtomicReference<Path> ret = new AtomicReference<>(null);
|
||||||
|
en.hdir.walk(File.separator, (path, name, entry) -> {
|
||||||
|
if(entry.getType() == HashedEntry.Type.DIR) return HashedDir.WalkAction.CONTINUE;
|
||||||
|
HashedFile tfile = (HashedFile) entry;
|
||||||
|
if(tfile.isSame(file))
|
||||||
|
{
|
||||||
|
LogHelper.dev("[DIR:%s] Found file %s in %s", en.name, name, path);
|
||||||
|
Path tdir = Paths.get(en.fullPath).resolve(path);
|
||||||
|
try {
|
||||||
|
if(tfile.isSame(tdir, true))
|
||||||
|
{
|
||||||
|
LogHelper.dev("[DIR:%s] Confirmed file %s in %s", en.name, name, path);
|
||||||
|
ret.set(tdir);
|
||||||
|
return HashedDir.WalkAction.STOP;
|
||||||
|
}
|
||||||
|
} catch (IOException e)
|
||||||
|
{
|
||||||
|
LogHelper.error("Check file error %s %s", e.getClass().getName(), e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return HashedDir.WalkAction.CONTINUE;
|
||||||
|
});
|
||||||
|
return ret.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void preDownload(UpdateRequest request, UpdateRequestEvent e, List<ListDownloader.DownloadTask> adds) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void postDownload(UpdateRequest request, UpdateRequestEvent e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void postUpdate(UpdateRequest request, UpdateRequestEvent e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
package ru.gravit.launcher.console;
|
||||||
|
|
||||||
|
import ru.gravit.launcher.managers.SettingsManager;
|
||||||
|
import ru.gravit.utils.command.Command;
|
||||||
|
import ru.gravit.utils.helper.LogHelper;
|
||||||
|
|
||||||
|
public class FeatureCommand extends Command {
|
||||||
|
@Override
|
||||||
|
public String getArgsDescription() {
|
||||||
|
return "[feature] [true/false]";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUsageDescription() {
|
||||||
|
return "Enable or disable feature";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invoke(String... args) throws Exception {
|
||||||
|
verifyArgs(args, 2);
|
||||||
|
boolean enabled = Boolean.valueOf(args[1]);
|
||||||
|
switch (args[0])
|
||||||
|
{
|
||||||
|
case "store":
|
||||||
|
{
|
||||||
|
SettingsManager.settings.featureStore = enabled;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
LogHelper.info("Features: [store]");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LogHelper.info("Feature %s %s", args[0], enabled ? "enabled" : "disabled");
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
package ru.gravit.launcher.console;
|
package ru.gravit.launcher.console;
|
||||||
|
|
||||||
import ru.gravit.launcher.managers.ConsoleManager;
|
import ru.gravit.launcher.managers.ConsoleManager;
|
||||||
|
import ru.gravit.launcher.managers.SettingsManager;
|
||||||
import ru.gravit.utils.command.Command;
|
import ru.gravit.utils.command.Command;
|
||||||
import ru.gravit.utils.helper.LogHelper;
|
import ru.gravit.utils.helper.LogHelper;
|
||||||
|
|
||||||
|
@ -22,6 +23,8 @@ public void invoke(String... args) throws Exception {
|
||||||
LogHelper.info("Unlock successful");
|
LogHelper.info("Unlock successful");
|
||||||
ConsoleManager.unlock();
|
ConsoleManager.unlock();
|
||||||
ConsoleManager.handler.unregisterCommand("unlock");
|
ConsoleManager.handler.unregisterCommand("unlock");
|
||||||
|
LogHelper.info("Write unlock key");
|
||||||
|
SettingsManager.settings.consoleUnlockKey = args[0];
|
||||||
} else {
|
} else {
|
||||||
LogHelper.error("Unlock key incorrect");
|
LogHelper.error("Unlock key incorrect");
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
package ru.gravit.launcher.console.store;
|
||||||
|
|
||||||
|
import ru.gravit.launcher.NewLauncherSettings;
|
||||||
|
import ru.gravit.launcher.managers.SettingsManager;
|
||||||
|
import ru.gravit.utils.command.Command;
|
||||||
|
import ru.gravit.utils.helper.LogHelper;
|
||||||
|
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
|
||||||
|
public class CopyStoreDirCommand extends Command {
|
||||||
|
@Override
|
||||||
|
public String getArgsDescription() {
|
||||||
|
return "[index] [overwrite(true/false)]";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUsageDescription() {
|
||||||
|
return "Copy dir in GravitLauncherStore";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invoke(String... args) throws Exception {
|
||||||
|
verifyArgs(args, 2);
|
||||||
|
int ind = 1;
|
||||||
|
int index = Integer.valueOf(args[0]);
|
||||||
|
boolean overwrite = Boolean.valueOf(args[1]);
|
||||||
|
for(NewLauncherSettings.HashedStoreEntry e : SettingsManager.settings.lastHDirs)
|
||||||
|
{
|
||||||
|
if(ind == index)
|
||||||
|
{
|
||||||
|
LogHelper.info("Copy [%d] FullPath: %s name: %s", ind, e.fullPath, e.name);
|
||||||
|
Path path = Paths.get(e.fullPath);
|
||||||
|
if(!Files.isDirectory(path))
|
||||||
|
{
|
||||||
|
LogHelper.error("Directory %s not found", path.toAbsolutePath().toString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Path target = Paths.get(SettingsManager.settings.updatesDirPath).resolve(e.name);
|
||||||
|
if(Files.exists(target) && !overwrite)
|
||||||
|
{
|
||||||
|
LogHelper.error("Directory %s found, flag overwrite not found", target.toAbsolutePath().toString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Files.copy(path, target);
|
||||||
|
}
|
||||||
|
ind++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
package ru.gravit.launcher.console.store;
|
||||||
|
|
||||||
|
import ru.gravit.launcher.NewLauncherSettings;
|
||||||
|
import ru.gravit.launcher.managers.SettingsManager;
|
||||||
|
import ru.gravit.utils.command.Command;
|
||||||
|
import ru.gravit.utils.helper.LogHelper;
|
||||||
|
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
|
||||||
|
public class LinkStoreDirCommand extends Command {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getArgsDescription() {
|
||||||
|
return "[index]";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUsageDescription() {
|
||||||
|
return "Create symlink to GravitLauncherStore directory";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invoke(String... args) throws Exception {
|
||||||
|
verifyArgs(args, 1);
|
||||||
|
int ind = 1;
|
||||||
|
int index = Integer.valueOf(args[0]);
|
||||||
|
for(NewLauncherSettings.HashedStoreEntry e : SettingsManager.settings.lastHDirs)
|
||||||
|
{
|
||||||
|
if(ind == index)
|
||||||
|
{
|
||||||
|
LogHelper.info("Copy [%d] FullPath: %s name: %s", ind, e.fullPath, e.name);
|
||||||
|
Path path = Paths.get(e.fullPath);
|
||||||
|
if(!Files.isDirectory(path))
|
||||||
|
{
|
||||||
|
LogHelper.error("Directory %s not found", path.toAbsolutePath().toString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Path target = Paths.get(SettingsManager.settings.updatesDirPath).resolve(e.name);
|
||||||
|
if(Files.exists(target))
|
||||||
|
{
|
||||||
|
LogHelper.error("Directory %s already exists", target.toAbsolutePath().toString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Files.createSymbolicLink(path, target);
|
||||||
|
}
|
||||||
|
ind++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package ru.gravit.launcher.console.store;
|
||||||
|
|
||||||
|
import ru.gravit.launcher.NewLauncherSettings;
|
||||||
|
import ru.gravit.launcher.managers.SettingsManager;
|
||||||
|
import ru.gravit.utils.command.Command;
|
||||||
|
import ru.gravit.utils.helper.LogHelper;
|
||||||
|
|
||||||
|
public class StoreListCommand extends Command {
|
||||||
|
@Override
|
||||||
|
public String getArgsDescription() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUsageDescription() {
|
||||||
|
return "List GravitLauncherStore";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invoke(String... args) throws Exception {
|
||||||
|
int ind = 1;
|
||||||
|
for(NewLauncherSettings.HashedStoreEntry e : SettingsManager.settings.lastHDirs)
|
||||||
|
{
|
||||||
|
LogHelper.info("[%d] FullPath: %s name: %s", ind, e.fullPath, e.name);
|
||||||
|
ind++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,13 @@
|
||||||
package ru.gravit.launcher.managers;
|
package ru.gravit.launcher.managers;
|
||||||
|
|
||||||
|
import ru.gravit.launcher.Launcher;
|
||||||
|
import ru.gravit.launcher.console.FeatureCommand;
|
||||||
import ru.gravit.launcher.console.UnlockCommand;
|
import ru.gravit.launcher.console.UnlockCommand;
|
||||||
import ru.gravit.launcher.console.admin.ExecCommand;
|
import ru.gravit.launcher.console.admin.ExecCommand;
|
||||||
import ru.gravit.launcher.console.admin.LogListenerCommand;
|
import ru.gravit.launcher.console.admin.LogListenerCommand;
|
||||||
|
import ru.gravit.launcher.console.store.CopyStoreDirCommand;
|
||||||
|
import ru.gravit.launcher.console.store.LinkStoreDirCommand;
|
||||||
|
import ru.gravit.launcher.console.store.StoreListCommand;
|
||||||
import ru.gravit.utils.command.BaseCommandCategory;
|
import ru.gravit.utils.command.BaseCommandCategory;
|
||||||
import ru.gravit.utils.command.CommandHandler;
|
import ru.gravit.utils.command.CommandHandler;
|
||||||
import ru.gravit.utils.command.JLineCommandHandler;
|
import ru.gravit.utils.command.JLineCommandHandler;
|
||||||
|
@ -15,10 +20,14 @@
|
||||||
import ru.gravit.utils.helper.LogHelper;
|
import ru.gravit.utils.helper.LogHelper;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
|
||||||
public class ConsoleManager {
|
public class ConsoleManager {
|
||||||
public static CommandHandler handler;
|
public static CommandHandler handler;
|
||||||
public static Thread thread;
|
public static Thread thread;
|
||||||
|
public static boolean isConsoleUnlock = false;
|
||||||
|
|
||||||
public static void initConsole() throws IOException {
|
public static void initConsole() throws IOException {
|
||||||
CommandHandler localCommandHandler;
|
CommandHandler localCommandHandler;
|
||||||
|
@ -46,14 +55,21 @@ public static void registerCommands() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean checkUnlockKey(String key) {
|
public static boolean checkUnlockKey(String key) {
|
||||||
return true;
|
return key.equals(Launcher.getConfig().oemUnlockKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void unlock() {
|
public static void unlock() {
|
||||||
handler.registerCommand("debug", new DebugCommand());
|
handler.registerCommand("debug", new DebugCommand());
|
||||||
|
handler.registerCommand("feature", new FeatureCommand());
|
||||||
BaseCommandCategory admin = new BaseCommandCategory();
|
BaseCommandCategory admin = new BaseCommandCategory();
|
||||||
admin.registerCommand("exec", new ExecCommand());
|
admin.registerCommand("exec", new ExecCommand());
|
||||||
admin.registerCommand("logListen", new LogListenerCommand());
|
admin.registerCommand("logListen", new LogListenerCommand());
|
||||||
handler.registerCategory(new CommandHandler.Category(admin, "admin", "Server admin commands"));
|
handler.registerCategory(new CommandHandler.Category(admin, "admin", "Server admin commands"));
|
||||||
|
BaseCommandCategory store = new BaseCommandCategory();
|
||||||
|
store.registerCommand("storeList", new StoreListCommand());
|
||||||
|
store.registerCommand("copyStoreDir", new CopyStoreDirCommand());
|
||||||
|
store.registerCommand("linkStoreDir", new LinkStoreDirCommand());
|
||||||
|
handler.registerCategory(new CommandHandler.Category(admin, "store", "Store admin commands"));
|
||||||
|
isConsoleUnlock = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
import ru.gravit.launcher.serialize.HInput;
|
import ru.gravit.launcher.serialize.HInput;
|
||||||
import ru.gravit.launcher.serialize.HOutput;
|
import ru.gravit.launcher.serialize.HOutput;
|
||||||
import ru.gravit.utils.helper.IOHelper;
|
import ru.gravit.utils.helper.IOHelper;
|
||||||
|
import ru.gravit.utils.helper.LogHelper;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
@ -24,6 +25,9 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
|
||||||
String fullPath = input.readString(1024);
|
String fullPath = input.readString(1024);
|
||||||
HashedDir dir = new HashedDir(input);
|
HashedDir dir = new HashedDir(input);
|
||||||
settings.lastHDirs.add(new NewLauncherSettings.HashedStoreEntry(dir, dirName, fullPath));
|
settings.lastHDirs.add(new NewLauncherSettings.HashedStoreEntry(dir, dirName, fullPath));
|
||||||
|
} catch (IOException e)
|
||||||
|
{
|
||||||
|
LogHelper.error("Skip file %s exception: %s", file.toAbsolutePath().toString(), e.getMessage());
|
||||||
}
|
}
|
||||||
return super.visitFile(file, attrs);
|
return super.visitFile(file, attrs);
|
||||||
}
|
}
|
||||||
|
@ -57,6 +61,14 @@ public void setConfig(NewLauncherSettings config) {
|
||||||
settings = config;
|
settings = config;
|
||||||
if (settings.updatesDirPath != null)
|
if (settings.updatesDirPath != null)
|
||||||
settings.updatesDir = Paths.get(settings.updatesDirPath);
|
settings.updatesDir = Paths.get(settings.updatesDirPath);
|
||||||
|
if(settings.consoleUnlockKey != null && !ConsoleManager.isConsoleUnlock)
|
||||||
|
{
|
||||||
|
if(ConsoleManager.checkUnlockKey(settings.consoleUnlockKey))
|
||||||
|
{
|
||||||
|
ConsoleManager.unlock();
|
||||||
|
LogHelper.info("Console auto unlocked");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
|
@ -69,6 +81,7 @@ public void loadHDirStore(Path storePath) throws IOException {
|
||||||
public void saveHDirStore(Path storeProjectPath) throws IOException {
|
public void saveHDirStore(Path storeProjectPath) throws IOException {
|
||||||
Files.createDirectories(storeProjectPath);
|
Files.createDirectories(storeProjectPath);
|
||||||
for (NewLauncherSettings.HashedStoreEntry e : settings.lastHDirs) {
|
for (NewLauncherSettings.HashedStoreEntry e : settings.lastHDirs) {
|
||||||
|
if(!e.needSave) continue;
|
||||||
Path file = storeProjectPath.resolve(e.name.concat(".bin"));
|
Path file = storeProjectPath.resolve(e.name.concat(".bin"));
|
||||||
if (!Files.exists(file)) Files.createFile(file);
|
if (!Files.exists(file)) Files.createFile(file);
|
||||||
try (HOutput output = new HOutput(IOHelper.newOutput(file))) {
|
try (HOutput output = new HOutput(IOHelper.newOutput(file))) {
|
||||||
|
|
|
@ -8,6 +8,7 @@ public class AutogenConfig {
|
||||||
private boolean isInitModules;
|
private boolean isInitModules;
|
||||||
public String guardType;
|
public String guardType;
|
||||||
public String secretKeyClient;
|
public String secretKeyClient;
|
||||||
|
public String oemUnlockKey;
|
||||||
public String guardLicenseName;
|
public String guardLicenseName;
|
||||||
public String guardLicenseKey;
|
public String guardLicenseKey;
|
||||||
public String guardLicenseEncryptKey;
|
public String guardLicenseEncryptKey;
|
||||||
|
|
|
@ -25,6 +25,7 @@ public static AutogenConfig getAutogenConfig() {
|
||||||
public final String projectname;
|
public final String projectname;
|
||||||
public final int clientPort;
|
public final int clientPort;
|
||||||
public String secretKeyClient;
|
public String secretKeyClient;
|
||||||
|
public String oemUnlockKey;
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
public final RSAPublicKey publicKey;
|
public final RSAPublicKey publicKey;
|
||||||
|
|
||||||
|
@ -45,6 +46,7 @@ public LauncherConfig(HInput input) throws IOException, InvalidKeySpecException
|
||||||
projectname = config.projectname;
|
projectname = config.projectname;
|
||||||
clientPort = config.clientPort;
|
clientPort = config.clientPort;
|
||||||
secretKeyClient = config.secretKeyClient;
|
secretKeyClient = config.secretKeyClient;
|
||||||
|
oemUnlockKey = config.oemUnlockKey;
|
||||||
|
|
||||||
isWarningMissArchJava = config.isWarningMissArchJava;
|
isWarningMissArchJava = config.isWarningMissArchJava;
|
||||||
guardLicenseEncryptKey = config.guardLicenseEncryptKey;
|
guardLicenseEncryptKey = config.guardLicenseEncryptKey;
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.zip.ZipEntry;
|
||||||
|
import java.util.zip.ZipInputStream;
|
||||||
|
|
||||||
public class ListDownloader {
|
public class ListDownloader {
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
|
@ -49,13 +51,36 @@ public void download(String base, List<DownloadTask> applies, Path dstDirFile, D
|
||||||
for (DownloadTask apply : applies) {
|
for (DownloadTask apply : applies) {
|
||||||
URI u = new URL(base.concat(IOHelper.urlEncode(apply.apply).replace("%2F", "/"))).toURI();
|
URI u = new URL(base.concat(IOHelper.urlEncode(apply.apply).replace("%2F", "/"))).toURI();
|
||||||
callback.stateChanged(apply.apply, 0L, apply.size);
|
callback.stateChanged(apply.apply, 0L, apply.size);
|
||||||
LogHelper.debug("Download URL: %s", u.toString());
|
Path targetPath = dstDirFile.resolve(apply.apply);
|
||||||
|
LogHelper.debug("Download URL: %s to file %s dir: %s", u.toString(), targetPath.toAbsolutePath().toString(), dstDirFile.toAbsolutePath().toString());
|
||||||
if (get == null) get = new HttpGet(u);
|
if (get == null) get = new HttpGet(u);
|
||||||
else {
|
else {
|
||||||
get.reset();
|
get.reset();
|
||||||
get.setURI(u);
|
get.setURI(u);
|
||||||
}
|
}
|
||||||
httpclient.execute(get, new FileDownloadResponseHandler(dstDirFile.resolve(apply.apply), apply, callback, totalCallback));
|
httpclient.execute(get, new FileDownloadResponseHandler(targetPath, apply, callback, totalCallback, false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void downloadZip(String base, Path dstDirFile, DownloadCallback callback, DownloadTotalCallback totalCallback) throws IOException, URISyntaxException {
|
||||||
|
/*try (CloseableHttpClient httpclient = HttpClients.custom()
|
||||||
|
.setRedirectStrategy(new LaxRedirectStrategy())
|
||||||
|
.build()) {
|
||||||
|
HttpGet get;
|
||||||
|
URI u = new URL(base).toURI();
|
||||||
|
LogHelper.debug("Download ZIP URL: %s", u.toString());
|
||||||
|
get = new HttpGet(u);
|
||||||
|
httpclient.execute(get, new FileDownloadResponseHandler(dstDirFile, callback, totalCallback, true));
|
||||||
|
}*/
|
||||||
|
try (ZipInputStream input = IOHelper.newZipInput(new URL(base))) {
|
||||||
|
for (ZipEntry entry = input.getNextEntry(); entry != null; entry = input.getNextEntry()) {
|
||||||
|
if (entry.isDirectory())
|
||||||
|
continue; // Skip directories
|
||||||
|
// Unpack entry
|
||||||
|
String name = entry.getName();
|
||||||
|
LogHelper.subInfo("Downloading file: '%s'", name);
|
||||||
|
Path fileName = IOHelper.toPath(name);
|
||||||
|
transfer(input, dstDirFile.resolve(fileName), fileName.toString(), entry.getSize(), callback, totalCallback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,24 +103,62 @@ static class FileDownloadResponseHandler implements ResponseHandler<Path> {
|
||||||
private final DownloadTask task;
|
private final DownloadTask task;
|
||||||
private final DownloadCallback callback;
|
private final DownloadCallback callback;
|
||||||
private final DownloadTotalCallback totalCallback;
|
private final DownloadTotalCallback totalCallback;
|
||||||
|
private final boolean zip;
|
||||||
|
|
||||||
public FileDownloadResponseHandler(Path target) {
|
public FileDownloadResponseHandler(Path target) {
|
||||||
this.target = target;
|
this.target = target;
|
||||||
this.task = null;
|
this.task = null;
|
||||||
|
this.zip = false;
|
||||||
callback = null;
|
callback = null;
|
||||||
totalCallback = null;
|
totalCallback = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public FileDownloadResponseHandler(Path target, DownloadTask task, DownloadCallback callback, DownloadTotalCallback totalCallback) {
|
public FileDownloadResponseHandler(Path target, DownloadTask task, DownloadCallback callback, DownloadTotalCallback totalCallback, boolean zip) {
|
||||||
this.target = target;
|
this.target = target;
|
||||||
this.task = task;
|
this.task = task;
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
this.totalCallback = totalCallback;
|
this.totalCallback = totalCallback;
|
||||||
|
this.zip = zip;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileDownloadResponseHandler(Path target, DownloadCallback callback, DownloadTotalCallback totalCallback, boolean zip) {
|
||||||
|
this.target = target;
|
||||||
|
this.task = null;
|
||||||
|
this.callback = callback;
|
||||||
|
this.totalCallback = totalCallback;
|
||||||
|
this.zip = zip;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Path handleResponse(HttpResponse response) throws IOException {
|
public Path handleResponse(HttpResponse response) throws IOException {
|
||||||
InputStream source = response.getEntity().getContent();
|
InputStream source = response.getEntity().getContent();
|
||||||
|
if(zip)
|
||||||
|
{
|
||||||
|
try(ZipInputStream input = IOHelper.newZipInput(source))
|
||||||
|
{
|
||||||
|
ZipEntry entry = input.getNextEntry();
|
||||||
|
while(entry != null)
|
||||||
|
{
|
||||||
|
if(entry.isDirectory())
|
||||||
|
{
|
||||||
|
entry = input.getNextEntry();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
long size = entry.getSize();
|
||||||
|
String filename = entry.getName();
|
||||||
|
Path target = this.target.resolve(filename);
|
||||||
|
if(callback != null)
|
||||||
|
{
|
||||||
|
callback.stateChanged(entry.getName(), 0, entry.getSize());
|
||||||
|
}
|
||||||
|
LogHelper.dev("Resolved filename %s to %s", filename, target.toAbsolutePath().toString());
|
||||||
|
transfer(source, target, filename, size, callback, totalCallback);
|
||||||
|
entry = input.getNextEntry();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
if (callback != null && task != null) {
|
if (callback != null && task != null) {
|
||||||
callback.stateChanged(task.apply, 0, task.size);
|
callback.stateChanged(task.apply, 0, task.size);
|
||||||
transfer(source, this.target, task.apply, task.size, callback, totalCallback);
|
transfer(source, this.target, task.apply, task.size, callback, totalCallback);
|
||||||
|
|
|
@ -9,6 +9,8 @@ public class UpdateRequestEvent extends RequestEvent {
|
||||||
public HashedDir hdir;
|
public HashedDir hdir;
|
||||||
@LauncherNetworkAPI
|
@LauncherNetworkAPI
|
||||||
public String url;
|
public String url;
|
||||||
|
@LauncherNetworkAPI
|
||||||
|
public boolean zip;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getType() {
|
public String getType() {
|
||||||
|
@ -17,10 +19,18 @@ public String getType() {
|
||||||
|
|
||||||
public UpdateRequestEvent(HashedDir hdir) {
|
public UpdateRequestEvent(HashedDir hdir) {
|
||||||
this.hdir = hdir;
|
this.hdir = hdir;
|
||||||
|
this.zip = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public UpdateRequestEvent(HashedDir hdir, String url) {
|
public UpdateRequestEvent(HashedDir hdir, String url) {
|
||||||
this.hdir = hdir;
|
this.hdir = hdir;
|
||||||
this.url = url;
|
this.url = url;
|
||||||
|
this.zip = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UpdateRequestEvent(HashedDir hdir, String url, boolean zip) {
|
||||||
|
this.hdir = hdir;
|
||||||
|
this.url = url;
|
||||||
|
this.zip = zip;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,20 @@
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public final class UpdateRequest extends Request<UpdateRequestEvent> implements RequestInterface {
|
public final class UpdateRequest extends Request<UpdateRequestEvent> implements RequestInterface {
|
||||||
|
public interface UpdateController
|
||||||
|
{
|
||||||
|
void preUpdate(UpdateRequest request, UpdateRequestEvent e) throws IOException;
|
||||||
|
void preDiff(UpdateRequest request, UpdateRequestEvent e) throws IOException;
|
||||||
|
void postDiff(UpdateRequest request, UpdateRequestEvent e,HashedDir.Diff diff) throws IOException;
|
||||||
|
void preDownload(UpdateRequest request, UpdateRequestEvent e, List<ListDownloader.DownloadTask> adds) throws IOException;
|
||||||
|
void postDownload(UpdateRequest request, UpdateRequestEvent e) throws IOException;
|
||||||
|
void postUpdate(UpdateRequest request, UpdateRequestEvent e) throws IOException;
|
||||||
|
}
|
||||||
|
private static UpdateController controller;
|
||||||
|
|
||||||
|
public static void setController(UpdateController controller) {
|
||||||
|
UpdateRequest.controller = controller;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getType() {
|
public String getType() {
|
||||||
|
@ -170,15 +184,22 @@ public double getTotalSizeMiB() {
|
||||||
public UpdateRequestEvent requestDo(StandartClientWebSocketService service) throws Exception {
|
public UpdateRequestEvent requestDo(StandartClientWebSocketService service) throws Exception {
|
||||||
LogHelper.debug("Start update request");
|
LogHelper.debug("Start update request");
|
||||||
UpdateRequestEvent e = (UpdateRequestEvent) service.sendRequest(this);
|
UpdateRequestEvent e = (UpdateRequestEvent) service.sendRequest(this);
|
||||||
|
if(controller != null) controller.preUpdate(this, e);
|
||||||
LogHelper.debug("Start update");
|
LogHelper.debug("Start update");
|
||||||
Launcher.profile.pushOptionalFile(e.hdir, !Launcher.profile.isUpdateFastCheck());
|
Launcher.profile.pushOptionalFile(e.hdir, !Launcher.profile.isUpdateFastCheck());
|
||||||
|
if(controller != null) controller.preDiff(this, e);
|
||||||
HashedDir.Diff diff = e.hdir.diff(localDir, matcher);
|
HashedDir.Diff diff = e.hdir.diff(localDir, matcher);
|
||||||
|
if(controller != null) controller.postDiff(this, e, diff);
|
||||||
final List<ListDownloader.DownloadTask> adds = new ArrayList<>();
|
final List<ListDownloader.DownloadTask> adds = new ArrayList<>();
|
||||||
|
if(controller != null) controller.preDownload(this, e, adds);
|
||||||
diff.mismatch.walk(IOHelper.CROSS_SEPARATOR, (path, name, entry) -> {
|
diff.mismatch.walk(IOHelper.CROSS_SEPARATOR, (path, name, entry) -> {
|
||||||
if (entry.getType().equals(HashedEntry.Type.FILE)) {
|
if (entry.getType().equals(HashedEntry.Type.FILE)) {
|
||||||
HashedFile file = (HashedFile) entry;
|
if(!entry.flag)
|
||||||
totalSize += file.size;
|
{
|
||||||
adds.add(new ListDownloader.DownloadTask(path, file.size));
|
HashedFile file = (HashedFile) entry;
|
||||||
|
totalSize += file.size;
|
||||||
|
adds.add(new ListDownloader.DownloadTask(path, file.size));
|
||||||
|
}
|
||||||
} else if (entry.getType().equals(HashedEntry.Type.DIR)) {
|
} else if (entry.getType().equals(HashedEntry.Type.DIR)) {
|
||||||
try {
|
try {
|
||||||
Files.createDirectories(dir.resolve(path));
|
Files.createDirectories(dir.resolve(path));
|
||||||
|
@ -186,13 +207,24 @@ public UpdateRequestEvent requestDo(StandartClientWebSocketService service) thro
|
||||||
LogHelper.error(ex);
|
LogHelper.error(ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return HashedDir.WalkAction.CONTINUE;
|
||||||
});
|
});
|
||||||
totalSize = diff.mismatch.size();
|
totalSize = diff.mismatch.size();
|
||||||
startTime = Instant.now();
|
startTime = Instant.now();
|
||||||
updateState("UnknownFile", 0L, 100);
|
updateState("UnknownFile", 0L, 100);
|
||||||
ListDownloader listDownloader = new ListDownloader();
|
ListDownloader listDownloader = new ListDownloader();
|
||||||
listDownloader.download(e.url, adds, dir, this::updateState, (add) -> totalDownloaded += add);
|
LogHelper.info("Download %s to %s", dirName, dir.toAbsolutePath().toString());
|
||||||
|
if(e.zip && !adds.isEmpty())
|
||||||
|
{
|
||||||
|
listDownloader.downloadZip(e.url, dir, this::updateState, (add) -> totalDownloaded += add);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
listDownloader.download(e.url, adds, dir, this::updateState, (add) -> totalDownloaded += add);
|
||||||
|
}
|
||||||
|
if(controller != null) controller.postDownload(this, e);
|
||||||
deleteExtraDir(dir, diff.extra, diff.extra.flag);
|
deleteExtraDir(dir, diff.extra, diff.extra.flag);
|
||||||
|
if(controller != null) controller.postUpdate(this, e);
|
||||||
LogHelper.debug("Update success");
|
LogHelper.debug("Update success");
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
@ -201,6 +233,11 @@ public UpdateRequestEvent requestDo(StandartClientWebSocketService service) thro
|
||||||
@LauncherNetworkAPI
|
@LauncherNetworkAPI
|
||||||
private final String dirName;
|
private final String dirName;
|
||||||
private transient final Path dir;
|
private transient final Path dir;
|
||||||
|
|
||||||
|
public Path getDir() {
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
|
||||||
private transient final FileNameMatcher matcher;
|
private transient final FileNameMatcher matcher;
|
||||||
|
|
||||||
private transient final boolean digest;
|
private transient final boolean digest;
|
||||||
|
|
|
@ -5,10 +5,12 @@
|
||||||
import ru.gravit.utils.helper.LogHelper;
|
import ru.gravit.utils.helper.LogHelper;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
public class WaitEventHandler implements ClientWebSocketService.EventHandler {
|
public class WaitEventHandler implements ClientWebSocketService.EventHandler {
|
||||||
public HashSet<ResultEvent> requests = new HashSet<>();
|
public Set<ResultEvent> requests = ConcurrentHashMap.newKeySet();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void process(ResultInterface result) {
|
public void process(ResultInterface result) {
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
import io.netty.util.CharsetUtil;
|
import io.netty.util.CharsetUtil;
|
||||||
import ru.gravit.utils.helper.LogHelper;
|
import ru.gravit.utils.helper.LogHelper;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
public class WebSocketClientHandler extends SimpleChannelInboundHandler<Object> {
|
public class WebSocketClientHandler extends SimpleChannelInboundHandler<Object> {
|
||||||
|
|
||||||
private final WebSocketClientHandshaker handshaker;
|
private final WebSocketClientHandshaker handshaker;
|
||||||
|
@ -30,6 +32,9 @@ public void handlerAdded(final ChannelHandlerContext ctx) throws Exception {
|
||||||
public void channelActive(final ChannelHandlerContext ctx) throws Exception {
|
public void channelActive(final ChannelHandlerContext ctx) throws Exception {
|
||||||
handshaker.handshake(ctx.channel());
|
handshaker.handshake(ctx.channel());
|
||||||
clientJSONPoint.onOpen();
|
clientJSONPoint.onOpen();
|
||||||
|
ctx.executor().schedule(() -> {
|
||||||
|
ctx.channel().writeAndFlush(new PingWebSocketFrame());
|
||||||
|
}, 20L, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -338,31 +338,44 @@ public void write(HOutput output) throws IOException {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void walk(CharSequence separator, WalkCallback callback) {
|
public void walk(CharSequence separator, WalkCallback callback) throws IOException {
|
||||||
String append = "";
|
String append = "";
|
||||||
walk(append, separator, callback, true);
|
walk(append, separator, callback, true);
|
||||||
}
|
}
|
||||||
|
public enum WalkAction
|
||||||
|
{
|
||||||
|
STOP, CONTINUE
|
||||||
|
}
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface WalkCallback {
|
public interface WalkCallback {
|
||||||
void walked(String path, String name, HashedEntry entry);
|
WalkAction walked(String path, String name, HashedEntry entry) throws IOException;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void walk(String append, CharSequence separator, WalkCallback callback, boolean noSeparator) {
|
private WalkAction walk(String append, CharSequence separator, WalkCallback callback, boolean noSeparator) throws IOException {
|
||||||
for (Map.Entry<String, HashedEntry> entry : map.entrySet()) {
|
for (Map.Entry<String, HashedEntry> entry : map.entrySet()) {
|
||||||
HashedEntry e = entry.getValue();
|
HashedEntry e = entry.getValue();
|
||||||
if (e.getType() == Type.FILE) {
|
if (e.getType() == Type.FILE) {
|
||||||
if (noSeparator)
|
if (noSeparator)
|
||||||
callback.walked(append + entry.getKey(), entry.getKey(), e);
|
{
|
||||||
|
WalkAction a = callback.walked(append + entry.getKey(), entry.getKey(), e);
|
||||||
|
if(a == WalkAction.STOP) return a;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
callback.walked(append + separator + entry.getKey(), entry.getKey(), e);
|
{
|
||||||
|
WalkAction a = callback.walked(append + separator + entry.getKey(), entry.getKey(), e);
|
||||||
|
if(a == WalkAction.STOP) return a;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
String newAppend;
|
String newAppend;
|
||||||
if (noSeparator) newAppend = append + entry.getKey();
|
if (noSeparator) newAppend = append + entry.getKey();
|
||||||
else newAppend = append + separator + entry.getKey();
|
else newAppend = append + separator + entry.getKey();
|
||||||
callback.walked(newAppend, entry.getKey(), e);
|
WalkAction a = callback.walked(newAppend, entry.getKey(), e);
|
||||||
((HashedDir) e).walk(newAppend, separator, callback, false);
|
if(a == WalkAction.STOP) return a;
|
||||||
|
a = ((HashedDir) e).walk(newAppend, separator, callback, false);
|
||||||
|
if(a == WalkAction.STOP) return a;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return WalkAction.CONTINUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,8 @@ public final class Version {
|
||||||
public final Type release;
|
public final Type release;
|
||||||
public static final int MAJOR = 5;
|
public static final int MAJOR = 5;
|
||||||
public static final int MINOR = 0;
|
public static final int MINOR = 0;
|
||||||
public static final int PATCH = 0;
|
public static final int PATCH = 1;
|
||||||
public static final int BUILD = 7;
|
public static final int BUILD = 1;
|
||||||
public static final Version.Type RELEASE = Version.Type.STABLE;
|
public static final Version.Type RELEASE = Version.Type.STABLE;
|
||||||
|
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
|
|
|
@ -75,6 +75,7 @@ public String readLine() throws IOException {
|
||||||
try {
|
try {
|
||||||
return reader.readLine();
|
return reader.readLine();
|
||||||
} catch (UserInterruptException e) {
|
} catch (UserInterruptException e) {
|
||||||
|
System.exit(0);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -113,7 +113,10 @@ public static void debug(String format, Object... args) {
|
||||||
|
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
public static void dev(String format, Object... args) {
|
public static void dev(String format, Object... args) {
|
||||||
dev(String.format(format, args));
|
if(isDevEnabled())
|
||||||
|
{
|
||||||
|
dev(String.format(format, args));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
|
|
Loading…
Reference in a new issue