From 5f7b0ca647986f18334a3b13e07485c0f0fe7af6 Mon Sep 17 00:00:00 2001
From: DrLeonardo <dmitriyleo7540@gmail.com>
Date: Mon, 27 May 2019 23:47:23 +0300
Subject: [PATCH 01/12] Fix #275 bug, added featureStore in settings overlay,
 fix download overlay

---
 .../dialog/overlay/processing/processing.css  |   9 +-
 .../dialog/overlay/settings/settings.fxml     |  60 +++---
 .../dialog/overlay/settings/settings.js       |  17 +-
 .../runtime/dialog/overlay/update/update.css  |   2 +-
 .../dialog/scenes/options/options.fxml        |   4 +-
 .../runtime/dialog/scenes/options/options.js  |   6 +-
 Launcher/runtime/dialog/styles.css            | 177 ++++++------------
 7 files changed, 100 insertions(+), 175 deletions(-)

diff --git a/Launcher/runtime/dialog/overlay/processing/processing.css b/Launcher/runtime/dialog/overlay/processing/processing.css
index c65c33dc..39c74e65 100644
--- a/Launcher/runtime/dialog/overlay/processing/processing.css
+++ b/Launcher/runtime/dialog/overlay/processing/processing.css
@@ -1,14 +1,11 @@
 /*-- DrLeonardo Design --*/
-
-#overlay>#description {
+#overlay > #description {
     -fx-font-size: 12pt;
     -fx-text-fill: #fff;
     -fx-wrap-text: true;
 }
 
-#overlay>#description.error {
-    -fx-text-fill: #CE5757;
+#overlay > #description.error {
+    -fx-text-fill: red;
 }
-
-
 /*-- DrLeonardo Design --*/
\ No newline at end of file
diff --git a/Launcher/runtime/dialog/overlay/settings/settings.fxml b/Launcher/runtime/dialog/overlay/settings/settings.fxml
index bfd1ae16..90358a27 100644
--- a/Launcher/runtime/dialog/overlay/settings/settings.fxml
+++ b/Launcher/runtime/dialog/overlay/settings/settings.fxml
@@ -13,60 +13,44 @@
 
 <!-- DrLeonardo Design -->
 
-<Pane fx:id="overlay" prefHeight="450.0" prefWidth="693.0" xmlns="http://javafx.com/javafx/8.0.201"
-      xmlns:fx="http://javafx.com/fxml/1">
+<Pane fx:id="overlay" prefHeight="450.0" prefWidth="693.0" xmlns="http://javafx.com/javafx/8.0.201" xmlns:fx="http://javafx.com/fxml/1">
     <children>
         <Pane id="holder" prefHeight="450.0" prefWidth="694.0">
             <children>
-                <JFXCheckBox fx:id="autoEnter" checkedColor="#5fd97a" layoutX="14.0" layoutY="137.0"
-                             text="Автовход на сервер" unCheckedColor="#909090"/>
-                <Text fill="#8c8c8c" layoutX="40.0" layoutY="153.0" strokeType="OUTSIDE" strokeWidth="0.0"
-                      text="Включение авто-входа означает что вы сразу после загрузки клиента попадете на сервер"
-                      wrappingWidth="636.9999872148037" y="15.0"/>
-                <JFXCheckBox fx:id="fullScreen" checkedColor="#5fd97a" layoutX="13.0" layoutY="260.0"
-                             text="Клиент в полный экран" unCheckedColor="#909090"/>
-                <Text fill="#8c8c8c" layoutX="40.0" layoutY="277.0" strokeType="OUTSIDE" strokeWidth="0.0"
-                      text="Включение данной функции позволяет запустить игру сразу в полноэкранном режиме"
-                      wrappingWidth="636.9999872148037" y="15.0"/>
-                <JFXCheckBox id="debug" checkedColor="#5fd97a" layoutX="13.0" layoutY="193.0" text="Режим Отладки"
-                             unCheckedColor="#909090"/>
-                <Text fill="#8c8c8c" layoutX="40.0" layoutY="208.0" strokeType="OUTSIDE" strokeWidth="0.0"
-                      text="Режим отладки позволяет просмотреть лог запуска и работы программы в реальном времени прямо из лаунчера, что упрощает поиск нужной информации"
-                      wrappingWidth="637.0000016447157" y="15.0"/>
+                <JFXCheckBox fx:id="autoEnter" checkedColor="#5fd97a" layoutX="14.0" layoutY="137.0" text="Автовход на сервер" unCheckedColor="#909090" />
+                <Text fill="#8c8c8c" layoutX="40.0" layoutY="153.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Включение авто-входа означает что вы сразу после загрузки клиента попадете на сервер" wrappingWidth="636.9999872148037" y="15.0" />
+                <JFXCheckBox fx:id="fullScreen" checkedColor="#5fd97a" layoutX="13.0" layoutY="244.0" text="Клиент в полный экран" unCheckedColor="#909090" />
+                <Text fill="#8c8c8c" layoutX="40.0" layoutY="261.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Включение данной функции позволяет запустить игру сразу в полноэкранном режиме" wrappingWidth="636.9999872148037" y="15.0" />
+                <JFXCheckBox id="debug" checkedColor="#5fd97a" layoutX="13.0" layoutY="183.0" text="Режим Отладки" unCheckedColor="#909090" />
+                <Text fill="#8c8c8c" layoutX="40.0" layoutY="198.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Режим отладки позволяет просмотреть лог запуска и работы программы в реальном времени прямо из лаунчера, что упрощает поиск нужной информации" wrappingWidth="637.0000016447157" y="15.0" />
                 <TextFlow layoutX="126.0" layoutY="15.0" prefHeight="16.0" prefWidth="112.0">
-                    <Text fx:id="ramLabel"/>
+                    <Text fx:id="ramLabel" />
                 </TextFlow>
-                <JFXButton fx:id="deleteDir" layoutX="370.0" layoutY="380.0" prefHeight="25.0" prefWidth="245.0"
-                           text="Удалить клиенты" textAlignment="CENTER" wrapText="true"/>
-                <JFXButton fx:id="changeDir" layoutY="419.0" prefHeight="30.0" prefWidth="200.0"
-                           text="Сменить директорию загрузки" textAlignment="CENTER" wrapText="true"/>
-                <Hyperlink id="dirLabel" alignment="BASELINE_LEFT" layoutX="201.0" layoutY="420.0" prefHeight="30.0"
-                           prefWidth="493.0" text="C:/Users"/>
-                <JFXButton fx:id="apply" defaultButton="true" layoutX="530.0" layoutY="380.0" prefHeight="23.0"
-                           prefWidth="100.0" text="Применить"/>
+                <JFXButton fx:id="deleteDir" layoutX="370.0" layoutY="380.0" prefHeight="25.0" prefWidth="245.0" text="Удалить клиенты" textAlignment="CENTER" wrapText="true" />
+                <JFXButton fx:id="changeDir" layoutY="419.0" prefHeight="30.0" prefWidth="200.0" text="Сменить директорию загрузки" textAlignment="CENTER" wrapText="true" />
+                <Hyperlink id="dirLabel" alignment="BASELINE_LEFT" layoutX="201.0" layoutY="420.0" prefHeight="30.0" prefWidth="493.0" text="C:/Users" />
+                <JFXButton fx:id="apply" defaultButton="true" layoutX="530.0" layoutY="380.0" prefHeight="23.0" prefWidth="100.0" text="Применить" />
                 <Text layoutX="16.0" layoutY="28.0">Выделение памяти:</Text>
-                <JFXSlider fx:id="ramSlider" layoutX="14.0" layoutY="76.0" prefHeight="14.0" prefWidth="663.0"/>
+                <JFXSlider fx:id="ramSlider" layoutX="14.0" layoutY="76.0" prefHeight="14.0" prefWidth="663.0" />
                 <Pane fx:id="transferDialog" prefHeight="425.0" prefWidth="694.0" visible="false">
                     <children>
-                        <Text fill="WHITE" layoutX="147.0" layoutY="198.0" strokeType="OUTSIDE" strokeWidth="0.0"
-                              text="Перенести все данные в новую директорию?" wrappingWidth="400.13671875">
+                        <Text fill="WHITE" layoutX="147.0" layoutY="198.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Перенести все данные в новую директорию?" wrappingWidth="400.13671875">
                             <font>
-                                <Font size="19.0"/>
+                                <Font size="19.0" />
                             </font>
                         </Text>
-                        <JFXButton fx:id="applyTransfer" layoutX="165.0" layoutY="226.0" mnemonicParsing="false"
-                                   prefHeight="25.0" prefWidth="124.0" text="Да, перенести!"/>
-                        <JFXButton fx:id="cancelTransfer" layoutX="379.0" layoutY="226.0" mnemonicParsing="false"
-                                   prefHeight="25.0" prefWidth="124.0" text="Нет, не нужно."/>
+                        <JFXButton fx:id="applyTransfer" layoutX="165.0" layoutY="226.0" mnemonicParsing="false" prefHeight="25.0" prefWidth="124.0" text="Да, перенести!" />
+                        <JFXButton fx:id="cancelTransfer" layoutX="379.0" layoutY="226.0" mnemonicParsing="false" prefHeight="25.0" prefWidth="124.0" text="Нет, не нужно." />
                     </children>
                 </Pane>
-                <Line endX="594.0" layoutX="100.0" layoutY="420.0" startX="-100.0" stroke="#5b3636"
-                      styleClass="lineHead"/>
+                <Line endX="594.0" layoutX="100.0" layoutY="420.0" startX="-100.0" stroke="#5b3636" styleClass="lineHead" />
+            <JFXCheckBox fx:id="featureStore" checkedColor="#5fd97a" layoutX="13.0" layoutY="292.0" text="Поиск файлов в других клиентах" unCheckedColor="#909090" />
+            <Text fill="#8c8c8c" layoutX="40.0" layoutY="309.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Используется для экономии вашего трафика, аналогичные файлы будут скопированы с других игровых клиентов" wrappingWidth="636.9999872148037" y="15.0" />
             </children>
         </Pane>
     </children>
     <stylesheets>
-        <URL value="@settings.css"/>
-        <URL value="@../../styles.css"/>
+        <URL value="@settings.css" />
+        <URL value="@../../styles.css" />
     </stylesheets>
 </Pane>
diff --git a/Launcher/runtime/dialog/overlay/settings/settings.js b/Launcher/runtime/dialog/overlay/settings/settings.js
index 590dea8b..17090929 100644
--- a/Launcher/runtime/dialog/overlay/settings/settings.js
+++ b/Launcher/runtime/dialog/overlay/settings/settings.js
@@ -33,6 +33,11 @@ var settingsOverlay = {
             }
         });
 
+        var featureStore = holder.lookup("#featureStore");
+        featureStore.setSelected(settings.featureStore);
+        featureStore.selectedProperty()["addListener(javafx.beans.value.ChangeListener)"](
+            function(o, ov, nv) settings.featureStore = nv);
+
         var fullScreenBox = holder.lookup("#fullScreen");
         fullScreenBox.setSelected(settings.fullScreen);
         fullScreenBox.selectedProperty()["addListener(javafx.beans.value.ChangeListener)"](
@@ -145,7 +150,7 @@ LogHelper.debug("Dir: %s", DirBridge.dir);
 var cliParams = {
     login: null, password: null, profile: -1, autoLogin: false,
     updatesDir: null, autoEnter: null, fullScreen: null, ram: -1,
-    offline: false,
+    offline: false, featureStore: null,
 
     init: function(params) {
         var named = params.getNamed();
@@ -167,6 +172,10 @@ var cliParams = {
         if (autoEnter !== null) {
             cliParams.autoEnter = java.lang.Boolean.parseBoolean(autoEnter);
         }
+        var featureStore = named.get("featureStore");
+        if (featureStore !== null) {
+            cliParams.featureStore = java.lang.Boolean.parseBoolean(featureStore);
+        }
         var fullScreen = named.get("fullScreen");
         if (fullScreen !== null) {
             cliParams.fullScreen = java.lang.Boolean.parseBoolean(fullScreen);
@@ -175,7 +184,6 @@ var cliParams = {
         if (ram !== null) {
             cliParams.ram = java.lang.Integer.parseInt(ram);
         }
-
         var offline = named.get("offline");
         if (offline !== null) {
             cliParams.offline = java.lang.Boolean.parseBoolean(offline);
@@ -192,19 +200,20 @@ var cliParams = {
         if (cliParams.profile >= 0) {
             settings.profile = cliParams.profile;
         }
-
         if (cliParams.updatesDir !== null) {
         }
         if (cliParams.autoEnter !== null) {
             settings.autoLogin = cliParams.autoEnter;
         }
+        if (cliParams.featureStore !== null) {
+            settings.featureStore = cliParams.featureStore;
+        }
         if (cliParams.fullScreen !== null) {
             settings.fullScreen = cliParams.fullScreen;
         }
         if (cliParams.ram >= 0) {
             settingsOverlay.setRAM(cliParams.ram);
         }
-
         if (cliParams.offline !== null) {
             settings.offline = cliParams.offline;
         }
diff --git a/Launcher/runtime/dialog/overlay/update/update.css b/Launcher/runtime/dialog/overlay/update/update.css
index 51324077..4035391a 100644
--- a/Launcher/runtime/dialog/overlay/update/update.css
+++ b/Launcher/runtime/dialog/overlay/update/update.css
@@ -20,7 +20,7 @@ #overlay > #description.error {
 }
 
 .downloadPane {
-    -fx-background-color: rgba(0, 0, 0, 0.1);
+    -fx-background-color: rgba(0, 0, 0, 0.2);
 }
 
 /* Progress bar */
diff --git a/Launcher/runtime/dialog/scenes/options/options.fxml b/Launcher/runtime/dialog/scenes/options/options.fxml
index c0b42259..a0bb1ef0 100644
--- a/Launcher/runtime/dialog/scenes/options/options.fxml
+++ b/Launcher/runtime/dialog/scenes/options/options.fxml
@@ -18,9 +18,9 @@
        <Pane id="optionsPane" prefHeight="450.0" prefWidth="692.0" styleClass="optionsPane">
            <children>
            <Line endX="595.0" layoutX="100.0" layoutY="46.0" startX="-100.0" stroke="#5b3636" styleClass="lineHead" />
-           <ScrollPane id="modlist" layoutY="46.0" prefHeight="402.0" prefWidth="693.0">
+           <ScrollPane id="modlist" layoutY="46.0" prefHeight="404.0" prefWidth="693.0">
                <content>
-                   <VBox prefHeight="397.0" prefWidth="678.0">
+                   <VBox prefHeight="394.0" prefWidth="678.0">
                        <children>
                        </children>
                        <padding>
diff --git a/Launcher/runtime/dialog/scenes/options/options.js b/Launcher/runtime/dialog/scenes/options/options.js
index b5959ff7..a5020d7e 100644
--- a/Launcher/runtime/dialog/scenes/options/options.js
+++ b/Launcher/runtime/dialog/scenes/options/options.js
@@ -129,7 +129,7 @@ var options = {
                                  profile.unmarkOptional(modFile);
                                  LogHelper.debug("Unselected mod %s", modFile.name);
                              }
-                             options.update();
+                             //options.update();
                          });
                         checkBoxList.add(testMod);
                         testMod.getStyleClass().add("modname");
@@ -137,11 +137,11 @@ var options = {
                              textDescr = new javafx.scene.text.Text(modDescription);
                              if(subLevel > 1) {
                                  for(var i = 1; i < subLevel; i++){
-                                    textDescr.setWrappingWidth(630-(25*i));
+                                    textDescr.setWrappingWidth(620-(25*i));
                                     textDescr.setTranslateX(25+(25*i));
                                  }
                              } else {
-                                 textDescr.setWrappingWidth(630);
+                                 textDescr.setWrappingWidth(620);
                                  textDescr.setTranslateX(25);
                              }
                              textDescr.setTextAlignment(javafx.scene.text.TextAlignment.JUSTIFY);
diff --git a/Launcher/runtime/dialog/styles.css b/Launcher/runtime/dialog/styles.css
index f382a466..d26cc8e4 100644
--- a/Launcher/runtime/dialog/styles.css
+++ b/Launcher/runtime/dialog/styles.css
@@ -1,15 +1,10 @@
 /*-- DrLeonardo Design --*/
-
-Button,
-CheckBox,
-ComboBox,
-RadioButton {
-    -fx-cursor: hand;
+Button, CheckBox, ComboBox, RadioButton {
+	-fx-cursor: hand;
 }
 
 
 /* Backgrounds */
-
 #layout {
     -fx-background-color: transparent;
     -fx-background-size: cover;
@@ -17,61 +12,48 @@ #layout {
     -fx-pref-height: 450px;
     -fx-background-image: url('images/background.jpg');
 }
-
 #background {
     -fx-background-color: #fff;
 }
-
-
 /** Labels **/
-
-#background>#settingsTitle {
+#background > #settingsTitle {
     -fx-font-size: 14pt;
     -fx-alignment: baseline-center;
 }
 
-#serverLabel {
+#serverLabel{
     -fx-text-fill: #323232;
 }
 
-#serverStatus {
+#serverStatus{
     -fx-text-fill: #323232;
     -fx-pref-width: 120px;
     -fx-pref-height: 25px;
 }
 
-
 /* 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 );
 }
 
-
 /** Errors **/
-
-#errormessage {
+#errormessage{
     -fx-background-color: transparent;
     -fx-text-alignment: center;
     -fx-text-fill: #CE5757;
 }
 
-.error {
+.error{
     -fx-text-fill: #CE5757;
 }
 
-
 /* bars */
-
 #bar {
     -fx-background-color: #323232;
     -fx-pref-width: 46px;
     -fx-pref-height: 450px;
 }
-
-
 /** buttons in bar **/
-
 #close {
     -fx-background-position: center;
     -jfx-button-type: FLAT;
@@ -80,12 +62,7 @@ #close {
     -fx-pref-width: 46px;
     -fx-pref-height: 45px;
 }
-
-#hide,
-#back,
-#goConsole,
-#settings,
-#discord {
+#hide, #back, #goConsole, #settings, #discord {
     -fx-background-position: center;
     -jfx-button-type: FLAT;
     -fx-background-radius: 0;
@@ -93,23 +70,21 @@ #discord {
     -fx-pref-height: 45px;
 }
 
-#logout {
-    -fx-text-fill: #323232;
-    -fx-font-size: 12;
-    -fx-font-weight: normal;
-    -fx-border-color: #CE5757;
-    -fx-border-width: 1;
-    -fx-background-color: transparent;
-    -fx-padding: 0;
+#logout{
+    -fx-text-fill:#323232;
+    -fx-font-size:12;
+    -fx-font-weight:normal;
+    -fx-border-color:#CE5757;
+    -fx-border-width:1;
+    -fx-background-color:transparent;
+    -fx-padding:0;
 }
-
 #logout:hover,
-#logout:focus {
-    -fx-text-fill: #ff6a5e;
+#logout:focus{
+    -fx-text-fill:#ff6a5e;
 }
-
-#logout:pressed {
-    -fx-border-color: #cb4d43;
+#logout:pressed{
+    -fx-border-color:#cb4d43;
 }
 
 #send {
@@ -122,13 +97,9 @@ #send {
     -fx-pref-height: 30px;
 }
 
-#send:pressed {
-    -fx-background-color: #d8d8d8;
-}
-
+#send:pressed { -fx-background-color: #d8d8d8; }
 
 /* LoginMenu */
-
 #authPane {
     -fx-background-color: rgba(255, 255, 255, 0.71);
     -fx-pref-width: 270px;
@@ -142,9 +113,7 @@ #logo {
     -fx-pref-height: 32px;
 }
 
-
 /** Buttons & textarea**/
-
 .auth {
     -jfx-button-type: FLAT;
     -fx-font-weight: bold;
@@ -154,22 +123,18 @@ .auth {
     -fx-text-fill: #ffffff;
     -fx-pref-width: 200px;
     -fx-pref-height: 45px;
-    -fx-effect: dropshadow(gaussian, rgba(23, 25, 29, 0.3), 15, 0, 0, 3);
+    -fx-effect: dropshadow(gaussian, rgba(23, 25, 29, 0.3), 15,0,0,3);
 }
 
-.auth:hover,
-.auth:pressed {
-    -fx-background-color: #75e18c;
-}
+.auth:hover, .auth:pressed { -fx-background-color: #75e18c; }
 
-#password,
-#login {
+#password, #login {
     -fx-background-radius: 0;
     -fx-pref-width: 200px;
     -fx-pref-height: 30px;
 }
 
-.text-input {
+.text-input{
     -fx-focus-color: transparent;
     -fx-background-repeat: no-repeat;
     -fx-text-fill: #909090;
@@ -180,9 +145,7 @@ .text-input {
     -fx-font-weight: bold;
 }
 
-
 /** Hyperlink **/
-
 #link {
     -fx-font-weight: bold;
     -fx-font-size: 7pt;
@@ -192,28 +155,21 @@ #link {
     -fx-pref-height: 17px;
 }
 
-#link:hover,
-#link:pressed {
-    -fx-opacity: 0.8;
-}
-
+#link:hover, #link:pressed { -fx-opacity: 0.8; }
 
 /** CheckBox & ComboBox**/
-
-#rememberchb {
+#rememberchb{
     -fx-font-size: 13;
     -fx-text-fill: #909090;
     -fx-pref-width: 145px;
     -fx-pref-height: 30px;
 }
-
 #combologin {
     -fx-text-fill: #909090;
     -fx-prompt-text-fill: #909090;
     -fx-pref-width: 200px;
     -fx-pref-height: 30px;
 }
-
 .combologin,
 .combologin {
     -fx-font-size: 13px;
@@ -231,7 +187,7 @@ .combologin .list-cell {
 .combologin-popup .list-view {
     -fx-background-color: white, white;
     -fx-background-insets: 0, 1;
-    -fx-effect: dropshadow( three-pass-box, rgba(0, 0, 0, 0.6), 8, 0.0, 0, 0);
+    -fx-effect: dropshadow( three-pass-box , rgba(0,0,0,0.6) , 8, 0.0 , 0 , 0 );
 }
 
 .combologin .list-cell:filled:selected .text,
@@ -244,44 +200,40 @@ .combologin .arrow {
     -fx-background-color: #5fd97a;
 }
 
-.combologin-popup .list-view .list-cell {
+.combologin-popup .list-view .list-cell
+{
     -fx-background-color: white;
 }
 
-.combologin-popup .list-view .list-cell:filled:selected,
-.combologin-popup .list-view .list-cell:filled:selected:hover {
+.combologin-popup .list-view .list-cell:filled:selected, .combologin-popup .list-view .list-cell:filled:selected:hover
+{
     -fx-background: -fx-accent;
     -fx-background-color: -fx-selection-bar;
     -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-text-fill: #909090;
 }
 
-
 /** web**/
-
 #news {
     -fx-background-color: transparent;
     -fx-pref-width: 423px;
     -fx-pref-height: 450px;
 }
 
-
 /* MenuPane */
-
 .serverentrance {
     -fx-background-color: rgba(255, 255, 255, 0.71);
     -fx-pref-width: 386px;
     -fx-pref-height: 450px;
 }
 
-
 /** buttons **/
-
-.clientLaunch {
+.clientLaunch{
     -jfx-button-type: FLAT;
     -fx-font-weight: bold;
     -fx-font-size: 16pt;
@@ -289,25 +241,17 @@ .clientLaunch {
     -fx-background-color: #5fd97a;
     -fx-text-fill: #ffffff;
 }
-
-.clientSettings {
+.clientSettings{
     -fx-background-position: center;
     -jfx-button-type: FLAT;
     -fx-background-color: #5fd97a;
     -fx-background-radius: 0;
 }
 
-.clientLaunch:hover,
-.clientLaunch:pressed {
-    -fx-background-color: #75e18c;
-}
-
+.clientLaunch:hover, .clientLaunch:pressed { -fx-background-color: #75e18c; }
 
 /* Pressets options */
-
-.pressetLight,
-.pressetMedium,
-.pressetHigh {
+.pressetLight, .pressetMedium, .pressetHigh {
     -jfx-toggle-color: #5fd97a;
     -jfx-untoggle-color: #FAFAFA;
     -jfx-toggle-line-color: rgba(116, 192, 133, 0.79);
@@ -316,9 +260,7 @@ .pressetHigh {
     -jfx-disable-visual-focus: false;
 }
 
-
 /* Scrolls */
-
 .scroll-pane {
     -fx-background-color: transparent;
 }
@@ -356,14 +298,12 @@ .scroll-pane>.corner {
     -fx-background-color: rgba(0, 0, 0, 0.19);
 }
 
-
 /* OptionsPane */
-
-#optionsPane>#modlist {
+#optionsPane > #modlist {
     -fx-background-color: transparent;
 }
 
-#optionsPane>#modlist>.viewport {
+#optionsPane > #modlist > .viewport {
     -fx-background-color: transparent;
 }
 
@@ -392,44 +332,39 @@ .separator *.line {
     -fx-border-width: 0 0 10 0;
 }
 
-#serverlist {
+#serverlist{
+    -fx-background-color: transparent;
+}
+#serverlist > .viewport {
     -fx-background-color: transparent;
 }
 
-#serverlist>.viewport {
+#serverdesc{
+    -fx-background-color: transparent;
+}
+#serverdesc > .viewport {
     -fx-background-color: transparent;
 }
 
-#serverdesc {
+#serverinfo{
+    -fx-background-color: transparent;
+}
+#serverinfo > .viewport {
     -fx-background-color: transparent;
 }
 
-#serverdesc>.viewport {
-    -fx-background-color: transparent;
-}
-
-#serverinfo {
-    -fx-background-color: transparent;
-}
-
-#serverinfo>.viewport {
-    -fx-background-color: transparent;
-}
-
-#servercontainer {
+#servercontainer{
     -fx-background-color: transparent;
     -jfx-button-type: FLAT;
     -fx-pref-width: 282px;
     -fx-pref-height: 75px;
 }
 
-.toggle-button:disabled {
+.toggle-button:disabled{
     -fx-opacity: 1.0;
 }
 
-.heading {
+.heading{
     -fx-text-fill: #555555;
 }
-
-
 /*-- DrLeonardo Design --*/
\ No newline at end of file

From 2176221c8eba52f0527cb1c69188178f12784b3f Mon Sep 17 00:00:00 2001
From: Gravit <gravit.min@ya.ru>
Date: Wed, 29 May 2019 08:15:32 +0700
Subject: [PATCH 02/12] =?UTF-8?q?[FEATURE]=20=D0=A0=D0=B0=D1=81=D1=88?=
 =?UTF-8?q?=D0=B8=D1=80=D0=B5=D0=BD=D0=BD=D1=8B=D0=B9=20=D1=82=D0=B8=D0=BF?=
 =?UTF-8?q?=20=D0=B7=D0=B0=D1=89=D0=B8=D1=82=D1=8B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../launcher/bridge/GravitGuardBridge.java    | 20 ++++
 .../launcher/guard/LauncherGravitGuard.java   | 96 +++++++++++++++++++
 .../launcher/guard/LauncherGuardManager.java  |  4 +
 3 files changed, 120 insertions(+)
 create mode 100644 Launcher/src/main/java/ru/gravit/launcher/bridge/GravitGuardBridge.java
 create mode 100644 Launcher/src/main/java/ru/gravit/launcher/guard/LauncherGravitGuard.java

diff --git a/Launcher/src/main/java/ru/gravit/launcher/bridge/GravitGuardBridge.java b/Launcher/src/main/java/ru/gravit/launcher/bridge/GravitGuardBridge.java
new file mode 100644
index 00000000..f3e266eb
--- /dev/null
+++ b/Launcher/src/main/java/ru/gravit/launcher/bridge/GravitGuardBridge.java
@@ -0,0 +1,20 @@
+package ru.gravit.launcher.bridge;
+
+import ru.gravit.launcher.LauncherAPI;
+
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+@LauncherAPI
+public class GravitGuardBridge {
+    @LauncherAPI
+    public static native void callGuard();
+    @LauncherAPI
+    public static int sendHTTPRequest(String strurl) throws IOException {
+        URL url = new URL(strurl);
+        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+        connection.setRequestMethod("GET");
+        connection.setRequestProperty("Content-Language", "en-US");
+        return connection.getResponseCode();
+    }
+}
diff --git a/Launcher/src/main/java/ru/gravit/launcher/guard/LauncherGravitGuard.java b/Launcher/src/main/java/ru/gravit/launcher/guard/LauncherGravitGuard.java
new file mode 100644
index 00000000..a72e5b4a
--- /dev/null
+++ b/Launcher/src/main/java/ru/gravit/launcher/guard/LauncherGravitGuard.java
@@ -0,0 +1,96 @@
+package ru.gravit.launcher.guard;
+
+import ru.gravit.launcher.Launcher;
+import ru.gravit.launcher.LauncherConfig;
+import ru.gravit.launcher.bridge.GravitGuardBridge;
+import ru.gravit.launcher.client.ClientLauncher;
+import ru.gravit.launcher.client.ClientLauncherContext;
+import ru.gravit.launcher.client.DirBridge;
+import ru.gravit.utils.helper.IOHelper;
+import ru.gravit.utils.helper.JVMHelper;
+import ru.gravit.utils.helper.UnpackHelper;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Collections;
+import java.util.Map;
+
+//Используется для всех типов защит, совместимых с новым GravitGuard API
+public class LauncherGravitGuard implements LauncherGuardInterface {
+    public String protectToken;
+    public Path javaBinPath;
+
+    @Override
+    public String getName() {
+        return "wrapper";
+    }
+
+    @Override
+    public Path getJavaBinPath() {
+        if (JVMHelper.OS_TYPE == JVMHelper.OS.MUSTDIE) {
+            String projectName = Launcher.getConfig().projectname;
+            String wrapperUnpackName = JVMHelper.JVM_BITS == 64 ? projectName.concat("64.exe") : projectName.concat("32.exe");
+            return DirBridge.getGuardDir().resolve(wrapperUnpackName);
+        } else if(ClientLauncher.getJavaBinPath() != null)
+        {
+            javaBinPath = ClientLauncher.getJavaBinPath();
+            String projectName = Launcher.getConfig().projectname;
+            String wrapperUnpackName = JVMHelper.JVM_BITS == 64 ? projectName.concat("64.exe") : projectName.concat("32.exe");
+            return DirBridge.getGuardDir().resolve(wrapperUnpackName);
+        }
+        else
+            return IOHelper.resolveJavaBin(Paths.get(System.getProperty("java.home")));
+    }
+
+    @Override
+    public int getClientJVMBits() {
+        return JVMHelper.JVM_BITS;
+    }
+
+    @Override
+    public void init(boolean clientInstance) {
+        try {
+            String wrapperName = JVMHelper.JVM_BITS == 64 ? "wrapper64.exe" : "wrapper32.exe";
+            String projectName = Launcher.getConfig().projectname;
+            String wrapperUnpackName = JVMHelper.JVM_BITS == 64 ? projectName.concat("64.exe") : projectName.concat("32.exe");
+            String antiInjectName = JVMHelper.JVM_BITS == 64 ? "AntiInject64.dll" : "AntiInject32.dll";
+            UnpackHelper.unpack(Launcher.getResourceURL(wrapperName, "guard"), DirBridge.getGuardDir().resolve(wrapperUnpackName));
+            UnpackHelper.unpack(Launcher.getResourceURL(antiInjectName, "guard"), DirBridge.getGuardDir().resolve(antiInjectName));
+        } catch (IOException e) {
+            throw new SecurityException(e);
+        }
+        if(clientInstance) GravitGuardBridge.callGuard();
+    }
+
+    @Override
+    public void addCustomParams(ClientLauncherContext context) {
+        Collections.addAll(context.args, "-Djava.class.path=".concat(context.pathLauncher));
+    }
+
+    @Override
+    public void addCustomEnv(ClientLauncherContext context) {
+        Map<String, String> env = context.builder.environment();
+        if(javaBinPath == null)
+            env.put("JAVA_HOME", System.getProperty("java.home"));
+        else
+            env.put("JAVA_HOME", javaBinPath.toAbsolutePath().toString());
+        LauncherConfig config = Launcher.getConfig();
+        env.put("GUARD_BRIDGE", GravitGuardBridge.class.getName());
+        env.put("GUARD_USERNAME", context.playerProfile.username);
+        env.put("GUARD_PUBLICKEY", config.publicKey.getModulus().toString(16));
+        env.put("GUARD_PROJECTNAME", config.projectname);
+        if (protectToken != null)
+            env.put("GUARD_TOKEN", protectToken);
+        if (config.guardLicenseName != null)
+            env.put("GUARD_LICENSE_NAME", config.guardLicenseName);
+        if (config.guardLicenseKey != null) {
+            env.put("GUARD_LICENSE_KEY", config.guardLicenseKey);
+        }
+    }
+
+    @Override
+    public void setProtectToken(String token) {
+        protectToken = token;
+    }
+}
diff --git a/Launcher/src/main/java/ru/gravit/launcher/guard/LauncherGuardManager.java b/Launcher/src/main/java/ru/gravit/launcher/guard/LauncherGuardManager.java
index e636dd0d..63a10397 100644
--- a/Launcher/src/main/java/ru/gravit/launcher/guard/LauncherGuardManager.java
+++ b/Launcher/src/main/java/ru/gravit/launcher/guard/LauncherGuardManager.java
@@ -11,6 +11,10 @@ public class LauncherGuardManager {
     public static void initGuard(boolean clientInstance) {
         LauncherConfig config = Launcher.getConfig();
         switch (config.guardType) {
+            case "gravitguard": {
+                guard = new LauncherGravitGuard();
+                break;
+            }
             case "wrapper": {
                 guard = new LauncherWrapperGuard();
                 break;

From 377a4c921ff14e7aad3e63c26376b4b2fe5f9bb5 Mon Sep 17 00:00:00 2001
From: Gravit <gravit.min@ya.ru>
Date: Wed, 29 May 2019 08:22:37 +0700
Subject: [PATCH 03/12] =?UTF-8?q?[FIX]=20=D0=98=D1=81=D0=BF=D1=80=D0=B0?=
 =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=BE=D1=82=D0=BF=D1=80=D0=B0?=
 =?UTF-8?q?=D0=B2=D0=BA=D0=B0=20=D0=B8=D1=81=D0=BA=D0=BB=D1=8E=D1=87=D0=B5?=
 =?UTF-8?q?=D0=BD=D0=B8=D0=B9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../request/websockets/StandartClientWebSocketService.java    | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/LauncherAPI/src/main/java/ru/gravit/launcher/request/websockets/StandartClientWebSocketService.java b/LauncherAPI/src/main/java/ru/gravit/launcher/request/websockets/StandartClientWebSocketService.java
index a5372c44..bfdff933 100644
--- a/LauncherAPI/src/main/java/ru/gravit/launcher/request/websockets/StandartClientWebSocketService.java
+++ b/LauncherAPI/src/main/java/ru/gravit/launcher/request/websockets/StandartClientWebSocketService.java
@@ -63,7 +63,7 @@ public ResultInterface get() throws InterruptedException, ExecutionException {
             }
             ResultInterface result = event.result;
             waitEventHandler.requests.remove(event);
-            if (event.result.getType().equals("error")) {
+            if (event.result.getType().equals("error") || event.result.getType().equals("exception")) {
                 ErrorRequestEvent errorRequestEvent = (ErrorRequestEvent) event.result;
                 throw new ExecutionException(new RequestException(errorRequestEvent.error));
             }
@@ -80,7 +80,7 @@ public ResultInterface get(long timeout, TimeUnit unit) throws InterruptedExcept
             }
             ResultInterface result = event.result;
             waitEventHandler.requests.remove(event);
-            if (event.result.getType().equals("error")) {
+            if (event.result.getType().equals("error") || event.result.getType().equals("exception")) {
                 ErrorRequestEvent errorRequestEvent = (ErrorRequestEvent) event.result;
                 throw new ExecutionException(new RequestException(errorRequestEvent.error));
             }

From bee6429bede3d39f8363ca1f1506c5b21cfb02d0 Mon Sep 17 00:00:00 2001
From: Gravit <gravit.min@ya.ru>
Date: Fri, 31 May 2019 05:38:07 +0700
Subject: [PATCH 04/12] =?UTF-8?q?[FIX]=20=D0=92=D0=B5=D1=80=D0=BD=D1=83?=
 =?UTF-8?q?=D0=BB=20=D0=BD=D0=B0=20=D0=BC=D0=B5=D1=81=D1=82=D0=BE=20option?=
 =?UTF-8?q?s.update?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 Launcher/runtime/dialog/scenes/options/options.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Launcher/runtime/dialog/scenes/options/options.js b/Launcher/runtime/dialog/scenes/options/options.js
index a5020d7e..b7749643 100644
--- a/Launcher/runtime/dialog/scenes/options/options.js
+++ b/Launcher/runtime/dialog/scenes/options/options.js
@@ -129,7 +129,7 @@ var options = {
                                  profile.unmarkOptional(modFile);
                                  LogHelper.debug("Unselected mod %s", modFile.name);
                              }
-                             //options.update();
+                             options.update();
                          });
                         checkBoxList.add(testMod);
                         testMod.getStyleClass().add("modname");

From 3ecc4c3bf194a296bb7ae9b1195ac151033381d6 Mon Sep 17 00:00:00 2001
From: Gravit <gravit.min@ya.ru>
Date: Fri, 31 May 2019 05:40:19 +0700
Subject: [PATCH 05/12] [ANY] IDEA Reformat code

---
 .../ru/gravit/launchserver/LaunchServer.java  |  4 +-
 .../binary/EXEL4JLauncherBinary.java          |  2 +-
 .../binary/JARLauncherBinary.java             |  4 +-
 .../binary/tasks/MainBuildTask.java           |  2 +-
 .../websocket/json/update/UpdateResponse.java |  3 +-
 .../launcher/bridge/GravitGuardBridge.java    |  2 +
 .../client/LauncherUpdateController.java      | 47 ++++++---------
 .../launcher/console/FeatureCommand.java      |  9 +--
 .../console/store/CopyStoreDirCommand.java    | 12 ++--
 .../console/store/LinkStoreDirCommand.java    | 12 ++--
 .../console/store/StoreListCommand.java       |  3 +-
 .../launcher/guard/LauncherGravitGuard.java   | 10 ++--
 .../launcher/managers/SettingsManager.java    | 11 ++--
 .../launcher/downloader/ListDownloader.java   | 16 ++---
 .../gravit/launcher/request/UpdateAction.java | 60 -------------------
 .../request/update/UpdateRequest.java         | 33 +++++-----
 .../ru/gravit/launcher/hasher/HashedDir.java  | 19 +++---
 .../ru/gravit/utils/helper/LogHelper.java     |  3 +-
 18 files changed, 79 insertions(+), 173 deletions(-)
 delete mode 100644 LauncherAPI/src/main/java/ru/gravit/launcher/request/UpdateAction.java

diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/LaunchServer.java b/LaunchServer/src/main/java/ru/gravit/launchserver/LaunchServer.java
index 07a9e14b..e6f15e8d 100644
--- a/LaunchServer/src/main/java/ru/gravit/launchserver/LaunchServer.java
+++ b/LaunchServer/src/main/java/ru/gravit/launchserver/LaunchServer.java
@@ -265,8 +265,8 @@ public static class ExeConf {
         public String txtFileVersion;
         public String txtProductVersion;
     }
-    public static class NettyUpdatesBind
-    {
+
+    public static class NettyUpdatesBind {
         public String url;
         public boolean zip;
     }
diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/binary/EXEL4JLauncherBinary.java b/LaunchServer/src/main/java/ru/gravit/launchserver/binary/EXEL4JLauncherBinary.java
index 2f2142b7..0b754461 100644
--- a/LaunchServer/src/main/java/ru/gravit/launchserver/binary/EXEL4JLauncherBinary.java
+++ b/LaunchServer/src/main/java/ru/gravit/launchserver/binary/EXEL4JLauncherBinary.java
@@ -78,7 +78,7 @@ private void setConfig() {
         // Prepare JRE
         Jre jre = new Jre();
         jre.setMinVersion("1.8.0");
-        if(server.config.launch4j.setMaxVersion)
+        if (server.config.launch4j.setMaxVersion)
             jre.setMaxVersion(server.config.launch4j.maxVersion);
         jre.setRuntimeBits(Jre.RUNTIME_BITS_64_AND_32);
         jre.setJdkPreference(Jre.JDK_PREFERENCE_PREFER_JRE);
diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/binary/JARLauncherBinary.java b/LaunchServer/src/main/java/ru/gravit/launchserver/binary/JARLauncherBinary.java
index 5d2ee007..bf61117a 100644
--- a/LaunchServer/src/main/java/ru/gravit/launchserver/binary/JARLauncherBinary.java
+++ b/LaunchServer/src/main/java/ru/gravit/launchserver/binary/JARLauncherBinary.java
@@ -42,11 +42,11 @@ public JARLauncherBinary(LaunchServer server) throws IOException {
     public void init() {
         tasks.add(new PrepareBuildTask(server));
         tasks.add(new MainBuildTask(server));
-        if(server.config.launcher.attachLibraryBeforeProGuard) tasks.add(new AttachJarsTask(server));
+        if (server.config.launcher.attachLibraryBeforeProGuard) tasks.add(new AttachJarsTask(server));
         tasks.add(new ProGuardBuildTask(server));
         tasks.add(new AdditionalFixesApplyTask(server));
         tasks.add(new RadonBuildTask(server));
-        if(!server.config.launcher.attachLibraryBeforeProGuard) tasks.add(new AttachJarsTask(server));
+        if (!server.config.launcher.attachLibraryBeforeProGuard) tasks.add(new AttachJarsTask(server));
     }
 
     @Override
diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/binary/tasks/MainBuildTask.java b/LaunchServer/src/main/java/ru/gravit/launchserver/binary/tasks/MainBuildTask.java
index 255dfd59..90eb8e45 100644
--- a/LaunchServer/src/main/java/ru/gravit/launchserver/binary/tasks/MainBuildTask.java
+++ b/LaunchServer/src/main/java/ru/gravit/launchserver/binary/tasks/MainBuildTask.java
@@ -137,7 +137,7 @@ public Path process(Path inputJar) throws IOException {
             jaConfigurator.setGuardType(server.config.launcher.guardType);
             jaConfigurator.setWarningMissArchJava(server.config.isWarningMissArchJava);
             jaConfigurator.setEnv(server.config.env);
-            if(server.runtime.oemUnlockKey == null) server.runtime.oemUnlockKey = SecurityHelper.randomStringToken();
+            if (server.runtime.oemUnlockKey == null) server.runtime.oemUnlockKey = SecurityHelper.randomStringToken();
             jaConfigurator.setOemUnlockKey(server.runtime.oemUnlockKey);
             server.buildHookManager.registerAllClientModuleClass(jaConfigurator);
             reader.getCp().add(new JarFile(inputJar.toFile()));
diff --git a/LaunchServer/src/main/java/ru/gravit/launchserver/websocket/json/update/UpdateResponse.java b/LaunchServer/src/main/java/ru/gravit/launchserver/websocket/json/update/UpdateResponse.java
index b326f1c0..5e03c7ef 100644
--- a/LaunchServer/src/main/java/ru/gravit/launchserver/websocket/json/update/UpdateResponse.java
+++ b/LaunchServer/src/main/java/ru/gravit/launchserver/websocket/json/update/UpdateResponse.java
@@ -40,8 +40,7 @@ public void execute(ChannelHandlerContext ctx, Client client) {
         }
         String url = LaunchServer.server.config.netty.downloadURL.replace("%dirname%", dirName);
         boolean zip = false;
-        if (server.config.netty.bindings.get(dirName) != null)
-        {
+        if (server.config.netty.bindings.get(dirName) != null) {
             LaunchServer.NettyUpdatesBind bind = server.config.netty.bindings.get(dirName);
             url = bind.url;
             zip = bind.zip;
diff --git a/Launcher/src/main/java/ru/gravit/launcher/bridge/GravitGuardBridge.java b/Launcher/src/main/java/ru/gravit/launcher/bridge/GravitGuardBridge.java
index f3e266eb..cabe2cc6 100644
--- a/Launcher/src/main/java/ru/gravit/launcher/bridge/GravitGuardBridge.java
+++ b/Launcher/src/main/java/ru/gravit/launcher/bridge/GravitGuardBridge.java
@@ -5,10 +5,12 @@
 import java.io.IOException;
 import java.net.HttpURLConnection;
 import java.net.URL;
+
 @LauncherAPI
 public class GravitGuardBridge {
     @LauncherAPI
     public static native void callGuard();
+
     @LauncherAPI
     public static int sendHTTPRequest(String strurl) throws IOException {
         URL url = new URL(strurl);
diff --git a/Launcher/src/main/java/ru/gravit/launcher/client/LauncherUpdateController.java b/Launcher/src/main/java/ru/gravit/launcher/client/LauncherUpdateController.java
index be328d52..73a57835 100644
--- a/Launcher/src/main/java/ru/gravit/launcher/client/LauncherUpdateController.java
+++ b/Launcher/src/main/java/ru/gravit/launcher/client/LauncherUpdateController.java
@@ -33,47 +33,40 @@ 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)
-        {
+        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) {
+                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)
-                    {
+                if (lastEn.get() == null) {
+                    for (NewLauncherSettings.HashedStoreEntry en : SettingsManager.settings.lastHDirs) {
                         ret = tryFind(en, file);
-                        if(ret != null) {
+                        if (ret != null) {
                             lastEn.set(en);
                             break;
                         }
                     }
-                }
-                else {
+                } else {
                     ret = tryFind(lastEn.get(), file);
                 }
-                if(ret == null)
-                {
-                    for(NewLauncherSettings.HashedStoreEntry en : SettingsManager.settings.lastHDirs)
-                    {
+                if (ret == null) {
+                    for (NewLauncherSettings.HashedStoreEntry en : SettingsManager.settings.lastHDirs) {
                         ret = tryFind(en, file);
-                        if(ret != null) {
+                        if (ret != null) {
                             lastEn.set(en);
                             break;
                         }
                     }
                 }
-                if(ret != null)
-                {
+                if (ret != null) {
                     //Еще раз проверим корректность хеша
                     //Возможно эта проверка избыточна
                     //if(file.isSame(ret, true))
@@ -82,8 +75,7 @@ public void postDiff(UpdateRequest request, UpdateRequestEvent e, HashedDir.Diff
                         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))
-                        {
+                        try (InputStream input = IOHelper.newInput(ret)) {
                             IOHelper.transfer(input, source);
                         }
                         entry.flag = true;
@@ -94,25 +86,22 @@ public void postDiff(UpdateRequest request, UpdateRequestEvent e, HashedDir.Diff
             });
         }
     }
-    public Path tryFind(NewLauncherSettings.HashedStoreEntry en, HashedFile file) throws IOException
-    {
+
+    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;
+            if (entry.getType() == HashedEntry.Type.DIR) return HashedDir.WalkAction.CONTINUE;
             HashedFile tfile = (HashedFile) entry;
-            if(tfile.isSame(file))
-            {
+            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))
-                    {
+                    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)
-                {
+                } catch (IOException e) {
                     LogHelper.error("Check file error %s %s", e.getClass().getName(), e.getMessage());
                 }
             }
diff --git a/Launcher/src/main/java/ru/gravit/launcher/console/FeatureCommand.java b/Launcher/src/main/java/ru/gravit/launcher/console/FeatureCommand.java
index 07f9ffc8..79dd2b3c 100644
--- a/Launcher/src/main/java/ru/gravit/launcher/console/FeatureCommand.java
+++ b/Launcher/src/main/java/ru/gravit/launcher/console/FeatureCommand.java
@@ -19,15 +19,12 @@ public String getUsageDescription() {
     public void invoke(String... args) throws Exception {
         verifyArgs(args, 2);
         boolean enabled = Boolean.valueOf(args[1]);
-        switch (args[0])
-        {
-            case "store":
-            {
+        switch (args[0]) {
+            case "store": {
                 SettingsManager.settings.featureStore = enabled;
                 break;
             }
-            default:
-            {
+            default: {
                 LogHelper.info("Features: [store]");
                 return;
             }
diff --git a/Launcher/src/main/java/ru/gravit/launcher/console/store/CopyStoreDirCommand.java b/Launcher/src/main/java/ru/gravit/launcher/console/store/CopyStoreDirCommand.java
index 9731dba5..4b966ca5 100644
--- a/Launcher/src/main/java/ru/gravit/launcher/console/store/CopyStoreDirCommand.java
+++ b/Launcher/src/main/java/ru/gravit/launcher/console/store/CopyStoreDirCommand.java
@@ -26,20 +26,16 @@ public void invoke(String... args) throws Exception {
         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)
-            {
+        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))
-                {
+                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)
-                {
+                if (Files.exists(target) && !overwrite) {
                     LogHelper.error("Directory %s found, flag overwrite not found", target.toAbsolutePath().toString());
                     return;
                 }
diff --git a/Launcher/src/main/java/ru/gravit/launcher/console/store/LinkStoreDirCommand.java b/Launcher/src/main/java/ru/gravit/launcher/console/store/LinkStoreDirCommand.java
index a107e6d3..712a04a1 100644
--- a/Launcher/src/main/java/ru/gravit/launcher/console/store/LinkStoreDirCommand.java
+++ b/Launcher/src/main/java/ru/gravit/launcher/console/store/LinkStoreDirCommand.java
@@ -26,20 +26,16 @@ 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)
-            {
+        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))
-                {
+                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))
-                {
+                if (Files.exists(target)) {
                     LogHelper.error("Directory %s already exists", target.toAbsolutePath().toString());
                     return;
                 }
diff --git a/Launcher/src/main/java/ru/gravit/launcher/console/store/StoreListCommand.java b/Launcher/src/main/java/ru/gravit/launcher/console/store/StoreListCommand.java
index 14a68524..0770d172 100644
--- a/Launcher/src/main/java/ru/gravit/launcher/console/store/StoreListCommand.java
+++ b/Launcher/src/main/java/ru/gravit/launcher/console/store/StoreListCommand.java
@@ -19,8 +19,7 @@ public String getUsageDescription() {
     @Override
     public void invoke(String... args) throws Exception {
         int ind = 1;
-        for(NewLauncherSettings.HashedStoreEntry e : SettingsManager.settings.lastHDirs)
-        {
+        for (NewLauncherSettings.HashedStoreEntry e : SettingsManager.settings.lastHDirs) {
             LogHelper.info("[%d] FullPath: %s name: %s", ind, e.fullPath, e.name);
             ind++;
         }
diff --git a/Launcher/src/main/java/ru/gravit/launcher/guard/LauncherGravitGuard.java b/Launcher/src/main/java/ru/gravit/launcher/guard/LauncherGravitGuard.java
index a72e5b4a..de9bd32f 100644
--- a/Launcher/src/main/java/ru/gravit/launcher/guard/LauncherGravitGuard.java
+++ b/Launcher/src/main/java/ru/gravit/launcher/guard/LauncherGravitGuard.java
@@ -32,14 +32,12 @@ public Path getJavaBinPath() {
             String projectName = Launcher.getConfig().projectname;
             String wrapperUnpackName = JVMHelper.JVM_BITS == 64 ? projectName.concat("64.exe") : projectName.concat("32.exe");
             return DirBridge.getGuardDir().resolve(wrapperUnpackName);
-        } else if(ClientLauncher.getJavaBinPath() != null)
-        {
+        } else if (ClientLauncher.getJavaBinPath() != null) {
             javaBinPath = ClientLauncher.getJavaBinPath();
             String projectName = Launcher.getConfig().projectname;
             String wrapperUnpackName = JVMHelper.JVM_BITS == 64 ? projectName.concat("64.exe") : projectName.concat("32.exe");
             return DirBridge.getGuardDir().resolve(wrapperUnpackName);
-        }
-        else
+        } else
             return IOHelper.resolveJavaBin(Paths.get(System.getProperty("java.home")));
     }
 
@@ -60,7 +58,7 @@ public void init(boolean clientInstance) {
         } catch (IOException e) {
             throw new SecurityException(e);
         }
-        if(clientInstance) GravitGuardBridge.callGuard();
+        if (clientInstance) GravitGuardBridge.callGuard();
     }
 
     @Override
@@ -71,7 +69,7 @@ public void addCustomParams(ClientLauncherContext context) {
     @Override
     public void addCustomEnv(ClientLauncherContext context) {
         Map<String, String> env = context.builder.environment();
-        if(javaBinPath == null)
+        if (javaBinPath == null)
             env.put("JAVA_HOME", System.getProperty("java.home"));
         else
             env.put("JAVA_HOME", javaBinPath.toAbsolutePath().toString());
diff --git a/Launcher/src/main/java/ru/gravit/launcher/managers/SettingsManager.java b/Launcher/src/main/java/ru/gravit/launcher/managers/SettingsManager.java
index d6788e91..052dd999 100644
--- a/Launcher/src/main/java/ru/gravit/launcher/managers/SettingsManager.java
+++ b/Launcher/src/main/java/ru/gravit/launcher/managers/SettingsManager.java
@@ -25,8 +25,7 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
                 String fullPath = input.readString(1024);
                 HashedDir dir = new HashedDir(input);
                 settings.lastHDirs.add(new NewLauncherSettings.HashedStoreEntry(dir, dirName, fullPath));
-            } catch (IOException e)
-            {
+            } catch (IOException e) {
                 LogHelper.error("Skip file %s exception: %s", file.toAbsolutePath().toString(), e.getMessage());
             }
             return super.visitFile(file, attrs);
@@ -61,10 +60,8 @@ public void setConfig(NewLauncherSettings config) {
         settings = config;
         if (settings.updatesDirPath != null)
             settings.updatesDir = Paths.get(settings.updatesDirPath);
-        if(settings.consoleUnlockKey != null && !ConsoleManager.isConsoleUnlock)
-        {
-            if(ConsoleManager.checkUnlockKey(settings.consoleUnlockKey))
-            {
+        if (settings.consoleUnlockKey != null && !ConsoleManager.isConsoleUnlock) {
+            if (ConsoleManager.checkUnlockKey(settings.consoleUnlockKey)) {
                 ConsoleManager.unlock();
                 LogHelper.info("Console auto unlocked");
             }
@@ -81,7 +78,7 @@ public void loadHDirStore(Path storePath) throws IOException {
     public void saveHDirStore(Path storeProjectPath) throws IOException {
         Files.createDirectories(storeProjectPath);
         for (NewLauncherSettings.HashedStoreEntry e : settings.lastHDirs) {
-            if(!e.needSave) continue;
+            if (!e.needSave) continue;
             Path file = storeProjectPath.resolve(e.name.concat(".bin"));
             if (!Files.exists(file)) Files.createFile(file);
             try (HOutput output = new HOutput(IOHelper.newOutput(file))) {
diff --git a/LauncherAPI/src/main/java/ru/gravit/launcher/downloader/ListDownloader.java b/LauncherAPI/src/main/java/ru/gravit/launcher/downloader/ListDownloader.java
index 7646379c..d31a5344 100644
--- a/LauncherAPI/src/main/java/ru/gravit/launcher/downloader/ListDownloader.java
+++ b/LauncherAPI/src/main/java/ru/gravit/launcher/downloader/ListDownloader.java
@@ -62,6 +62,7 @@ public void download(String base, List<DownloadTask> applies, Path dstDirFile, D
             }
         }
     }
+
     public void downloadZip(String base, Path dstDirFile, DownloadCallback callback, DownloadTotalCallback totalCallback) throws IOException, URISyntaxException {
         /*try (CloseableHttpClient httpclient = HttpClients.custom()
                 .setRedirectStrategy(new LaxRedirectStrategy())
@@ -132,23 +133,18 @@ public FileDownloadResponseHandler(Path target, DownloadCallback callback, Downl
         @Override
         public Path handleResponse(HttpResponse response) throws IOException {
             InputStream source = response.getEntity().getContent();
-            if(zip)
-            {
-                try(ZipInputStream input = IOHelper.newZipInput(source))
-                {
+            if (zip) {
+                try (ZipInputStream input = IOHelper.newZipInput(source)) {
                     ZipEntry entry = input.getNextEntry();
-                    while(entry != null)
-                    {
-                        if(entry.isDirectory())
-                        {
+                    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)
-                        {
+                        if (callback != null) {
                             callback.stateChanged(entry.getName(), 0, entry.getSize());
                         }
                         LogHelper.dev("Resolved filename %s to %s", filename, target.toAbsolutePath().toString());
diff --git a/LauncherAPI/src/main/java/ru/gravit/launcher/request/UpdateAction.java b/LauncherAPI/src/main/java/ru/gravit/launcher/request/UpdateAction.java
deleted file mode 100644
index 9f80c671..00000000
--- a/LauncherAPI/src/main/java/ru/gravit/launcher/request/UpdateAction.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package ru.gravit.launcher.request;
-
-import ru.gravit.launcher.hasher.HashedEntry;
-import ru.gravit.launcher.serialize.HInput;
-import ru.gravit.launcher.serialize.HOutput;
-import ru.gravit.launcher.serialize.stream.EnumSerializer;
-import ru.gravit.launcher.serialize.stream.StreamObject;
-import ru.gravit.utils.helper.IOHelper;
-
-import java.io.IOException;
-
-public final class UpdateAction extends StreamObject {
-    public enum Type implements EnumSerializer.Itf {
-        CD(1), CD_BACK(2), GET(3), FINISH(255);
-        private static final EnumSerializer<Type> SERIALIZER = new EnumSerializer<>(Type.class);
-
-        public static Type read(HInput input) throws IOException {
-            return SERIALIZER.read(input);
-        }
-
-        private final int n;
-
-        Type(int n) {
-            this.n = n;
-        }
-
-        @Override
-        public int getNumber() {
-            return n;
-        }
-    }
-
-    public static final UpdateAction CD_BACK = new UpdateAction(Type.CD_BACK, null, null);
-
-    public static final UpdateAction FINISH = new UpdateAction(Type.FINISH, null, null);
-    // Instance
-    public final Type type;
-    public final String name;
-
-    public final HashedEntry entry;
-
-    public UpdateAction(HInput input) throws IOException {
-        type = Type.read(input);
-        name = type == Type.CD || type == Type.GET ? IOHelper.verifyFileName(input.readString(255)) : null;
-        entry = null;
-    }
-
-    public UpdateAction(Type type, String name, HashedEntry entry) {
-        this.type = type;
-        this.name = name;
-        this.entry = entry;
-    }
-
-    @Override
-    public void write(HOutput output) throws IOException {
-        EnumSerializer.write(output, type);
-        if (type == Type.CD || type == Type.GET)
-            output.writeString(name, 255);
-    }
-}
diff --git a/LauncherAPI/src/main/java/ru/gravit/launcher/request/update/UpdateRequest.java b/LauncherAPI/src/main/java/ru/gravit/launcher/request/update/UpdateRequest.java
index 8ae58501..931e6828 100644
--- a/LauncherAPI/src/main/java/ru/gravit/launcher/request/update/UpdateRequest.java
+++ b/LauncherAPI/src/main/java/ru/gravit/launcher/request/update/UpdateRequest.java
@@ -27,15 +27,20 @@
 import java.util.Objects;
 
 public final class UpdateRequest extends Request<UpdateRequestEvent> implements RequestInterface {
-    public interface UpdateController
-    {
+    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 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) {
@@ -184,18 +189,17 @@ public double getTotalSizeMiB() {
     public UpdateRequestEvent requestDo(StandartClientWebSocketService service) throws Exception {
         LogHelper.debug("Start update request");
         UpdateRequestEvent e = (UpdateRequestEvent) service.sendRequest(this);
-        if(controller != null) controller.preUpdate(this, e);
+        if (controller != null) controller.preUpdate(this, e);
         LogHelper.debug("Start update");
         Launcher.profile.pushOptionalFile(e.hdir, !Launcher.profile.isUpdateFastCheck());
-        if(controller != null) controller.preDiff(this, e);
+        if (controller != null) controller.preDiff(this, e);
         HashedDir.Diff diff = e.hdir.diff(localDir, matcher);
-        if(controller != null) controller.postDiff(this, e, diff);
+        if (controller != null) controller.postDiff(this, e, diff);
         final List<ListDownloader.DownloadTask> adds = new ArrayList<>();
-        if(controller != null) controller.preDownload(this, e, adds);
+        if (controller != null) controller.preDownload(this, e, adds);
         diff.mismatch.walk(IOHelper.CROSS_SEPARATOR, (path, name, entry) -> {
             if (entry.getType().equals(HashedEntry.Type.FILE)) {
-                if(!entry.flag)
-                {
+                if (!entry.flag) {
                     HashedFile file = (HashedFile) entry;
                     totalSize += file.size;
                     adds.add(new ListDownloader.DownloadTask(path, file.size));
@@ -214,17 +218,14 @@ public UpdateRequestEvent requestDo(StandartClientWebSocketService service) thro
         updateState("UnknownFile", 0L, 100);
         ListDownloader listDownloader = new ListDownloader();
         LogHelper.info("Download %s to %s", dirName, dir.toAbsolutePath().toString());
-        if(e.zip && !adds.isEmpty())
-        {
+        if (e.zip && !adds.isEmpty()) {
             listDownloader.downloadZip(e.url, dir, this::updateState, (add) -> totalDownloaded += add);
-        }
-        else
-        {
+        } else {
             listDownloader.download(e.url, adds, dir, this::updateState, (add) -> totalDownloaded += add);
         }
-        if(controller != null) controller.postDownload(this, e);
+        if (controller != null) controller.postDownload(this, e);
         deleteExtraDir(dir, diff.extra, diff.extra.flag);
-        if(controller != null) controller.postUpdate(this, e);
+        if (controller != null) controller.postUpdate(this, e);
         LogHelper.debug("Update success");
         return e;
     }
diff --git a/LauncherCore/src/main/java/ru/gravit/launcher/hasher/HashedDir.java b/LauncherCore/src/main/java/ru/gravit/launcher/hasher/HashedDir.java
index bb1327be..0fed474b 100644
--- a/LauncherCore/src/main/java/ru/gravit/launcher/hasher/HashedDir.java
+++ b/LauncherCore/src/main/java/ru/gravit/launcher/hasher/HashedDir.java
@@ -342,8 +342,8 @@ public void walk(CharSequence separator, WalkCallback callback) throws IOExcepti
         String append = "";
         walk(append, separator, callback, true);
     }
-    public enum WalkAction
-    {
+
+    public enum WalkAction {
         STOP, CONTINUE
     }
 
@@ -356,24 +356,21 @@ private WalkAction walk(String append, CharSequence separator, WalkCallback call
         for (Map.Entry<String, HashedEntry> entry : map.entrySet()) {
             HashedEntry e = entry.getValue();
             if (e.getType() == Type.FILE) {
-                if (noSeparator)
-                {
+                if (noSeparator) {
                     WalkAction a = callback.walked(append + entry.getKey(), entry.getKey(), e);
-                    if(a == WalkAction.STOP) return a;
-                }
-                else
-                {
+                    if (a == WalkAction.STOP) return a;
+                } else {
                     WalkAction a = callback.walked(append + separator + entry.getKey(), entry.getKey(), e);
-                    if(a == WalkAction.STOP) return a;
+                    if (a == WalkAction.STOP) return a;
                 }
             } else {
                 String newAppend;
                 if (noSeparator) newAppend = append + entry.getKey();
                 else newAppend = append + separator + entry.getKey();
                 WalkAction a = callback.walked(newAppend, entry.getKey(), e);
-                if(a == WalkAction.STOP) return a;
+                if (a == WalkAction.STOP) return a;
                 a = ((HashedDir) e).walk(newAppend, separator, callback, false);
-                if(a == WalkAction.STOP) return a;
+                if (a == WalkAction.STOP) return a;
             }
         }
         return WalkAction.CONTINUE;
diff --git a/LauncherCore/src/main/java/ru/gravit/utils/helper/LogHelper.java b/LauncherCore/src/main/java/ru/gravit/utils/helper/LogHelper.java
index 22c1649a..a1739758 100644
--- a/LauncherCore/src/main/java/ru/gravit/utils/helper/LogHelper.java
+++ b/LauncherCore/src/main/java/ru/gravit/utils/helper/LogHelper.java
@@ -113,8 +113,7 @@ public static void debug(String format, Object... args) {
 
     @LauncherAPI
     public static void dev(String format, Object... args) {
-        if(isDevEnabled())
-        {
+        if (isDevEnabled()) {
             dev(String.format(format, args));
         }
     }

From 4af4a002a72bd69a9102b6cf998a06aacde83095 Mon Sep 17 00:00:00 2001
From: Gravit <gravit.min@ya.ru>
Date: Fri, 31 May 2019 05:40:54 +0700
Subject: [PATCH 06/12] [ANY] Update modules

---
 modules | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/modules b/modules
index baf1e7fb..5c3aa4d1 160000
--- a/modules
+++ b/modules
@@ -1 +1 @@
-Subproject commit baf1e7fb820fd1f4a1031e517fea03632f9e57e6
+Subproject commit 5c3aa4d10e6973799315c5befed2ecb7cd98b203

From 27db641eae11f9297da91a68d3b19f0faaffcb42 Mon Sep 17 00:00:00 2001
From: Gravit <gravit.min@ya.ru>
Date: Fri, 31 May 2019 05:42:51 +0700
Subject: [PATCH 07/12] =?UTF-8?q?[FIX]=20=D0=98=D1=81=D0=BF=D1=80=D0=B0?=
 =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D0=BE=20=D1=84=D0=BE=D1=80=D0=BC=D0=B0?=
 =?UTF-8?q?=D1=82=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20=D0=BF?=
 =?UTF-8?q?=D1=80=D0=B8=20=D1=81=D0=BE=D1=85=D1=80=D0=B0=D0=BD=D0=B5=D0=BD?=
 =?UTF-8?q?=D0=B8=D0=B8=20=D0=BA=D0=BE=D0=BD=D1=84=D0=B8=D0=B3=D1=83=D1=80?=
 =?UTF-8?q?=D0=B0=D1=86=D0=B8=D0=B8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../main/java/ru/gravit/launcher/config/JsonConfigurable.java | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/LauncherAPI/src/main/java/ru/gravit/launcher/config/JsonConfigurable.java b/LauncherAPI/src/main/java/ru/gravit/launcher/config/JsonConfigurable.java
index 5e1883e0..9546e85d 100644
--- a/LauncherAPI/src/main/java/ru/gravit/launcher/config/JsonConfigurable.java
+++ b/LauncherAPI/src/main/java/ru/gravit/launcher/config/JsonConfigurable.java
@@ -33,7 +33,7 @@ public JsonConfigurable(Type type, Path configPath) {
     @LauncherAPI
     public void saveConfig(Path configPath) throws IOException {
         try (BufferedWriter writer = IOHelper.newWriter(configPath)) {
-            Launcher.gsonManager.gson.toJson(getConfig(), type, writer);
+            Launcher.gsonManager.configGson.toJson(getConfig(), type, writer);
         }
     }
 
@@ -41,7 +41,7 @@ public void saveConfig(Path configPath) throws IOException {
     public void loadConfig(Path configPath) throws IOException {
         if (generateConfigIfNotExists(configPath)) return;
         try (BufferedReader reader = IOHelper.newReader(configPath)) {
-            setConfig(Launcher.gsonManager.gson.fromJson(reader, type));
+            setConfig(Launcher.gsonManager.configGson.fromJson(reader, type));
         }
     }
 

From fdc9730e018ff066fcf570f7f90e2a3c3a1bd34d Mon Sep 17 00:00:00 2001
From: Gravit <gravit.min@ya.ru>
Date: Fri, 31 May 2019 05:44:14 +0700
Subject: [PATCH 08/12] [ANY] Release 5.0.2

---
 LauncherCore/src/main/java/ru/gravit/utils/Version.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/LauncherCore/src/main/java/ru/gravit/utils/Version.java b/LauncherCore/src/main/java/ru/gravit/utils/Version.java
index 5f729792..e314edd1 100644
--- a/LauncherCore/src/main/java/ru/gravit/utils/Version.java
+++ b/LauncherCore/src/main/java/ru/gravit/utils/Version.java
@@ -17,7 +17,7 @@ public final class Version {
     public final Type release;
     public static final int MAJOR = 5;
     public static final int MINOR = 0;
-    public static final int PATCH = 1;
+    public static final int PATCH = 2;
     public static final int BUILD = 1;
     public static final Version.Type RELEASE = Version.Type.STABLE;
 

From fe60d6b23434c1b0025126a162e3cb53d790980c Mon Sep 17 00:00:00 2001
From: Gravit <gravit.min@ya.ru>
Date: Fri, 31 May 2019 05:51:02 +0700
Subject: [PATCH 09/12] =?UTF-8?q?[FIX]=20=D0=A3=D0=BC=D0=B5=D0=BD=D1=8C?=
 =?UTF-8?q?=D1=88=D0=B5=D0=BD=20=D1=80=D0=B0=D0=B7=D0=BC=D0=B5=D1=80=20?=
 =?UTF-8?q?=D0=BB=D0=B0=D1=83=D0=BD=D1=87=D0=B5=D1=80=D0=B0=20=D0=B7=D0=B0?=
 =?UTF-8?q?=20=D1=81=D1=87=D0=B5=D1=82=20=D0=B8=D1=81=D0=BF=D0=BE=D0=BB?=
 =?UTF-8?q?=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F=20=D1=82=D0=BE?=
 =?UTF-8?q?=D0=BB=D1=8C=D0=BA=D0=BE=20=D0=BD=D0=B5=D0=BE=D0=B1=D1=85=D0=BE?=
 =?UTF-8?q?=D0=B4=D0=B8=D0=BC=D1=8B=D1=85=20=D1=87=D0=B0=D1=81=D1=82=D0=B5?=
 =?UTF-8?q?=D0=B9=20Netty?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 Launcher/build.gradle      | 2 +-
 LauncherAPI/build.gradle   | 2 +-
 ServerWrapper/build.gradle | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/Launcher/build.gradle b/Launcher/build.gradle
index f1e08d0d..55457b58 100644
--- a/Launcher/build.gradle
+++ b/Launcher/build.gradle
@@ -41,7 +41,7 @@ pack project(':LauncherAuthlib')
     bundle 'com.jfoenix:jfoenix:8.0.8'
     bundle 'de.jensd:fontawesomefx:8.9'
     bundle 'org.apache.httpcomponents:httpclient:4.5.7'
-    pack 'io.netty:netty-all:4.1.36.Final'
+    pack 'io.netty:netty-codec-http:4.1.36.Final'
     pack 'org.ow2.asm:asm-tree:7.1'
 }
 
diff --git a/LauncherAPI/build.gradle b/LauncherAPI/build.gradle
index 305be8ce..3ba17392 100644
--- a/LauncherAPI/build.gradle
+++ b/LauncherAPI/build.gradle
@@ -4,5 +4,5 @@
 dependencies {
     compile project(':LauncherCore')
     compileOnly 'org.apache.httpcomponents:httpclient:4.5.7'
-    compileOnly 'io.netty:netty-all:4.1.36.Final'
+    compileOnly 'io.netty:netty-codec-http:4.1.36.Final'
 }
diff --git a/ServerWrapper/build.gradle b/ServerWrapper/build.gradle
index 130f0c57..ecdddd82 100644
--- a/ServerWrapper/build.gradle
+++ b/ServerWrapper/build.gradle
@@ -29,7 +29,7 @@
 dependencies {
     pack project(':LauncherAuthlib')
     pack 'org.apache.httpcomponents:httpclient:4.5.7'
-    pack 'io.netty:netty-all:4.1.36.Final'
+    pack 'io.netty:netty-codec-http:4.1.36.Final'
 }
 
 shadowJar {

From 4cf828a948f13271587ef6445a0c8636fa0f6035 Mon Sep 17 00:00:00 2001
From: Yaroslavik <yaroslav4167@mail.ru>
Date: Fri, 31 May 2019 02:11:47 +0200
Subject: [PATCH 10/12] =?UTF-8?q?[FIX]=20=D0=9F=D1=80=D0=B0=D0=B2=D0=BA?=
 =?UTF-8?q?=D0=B0=20=D0=BE=D1=82=D0=BA=D0=B8=D0=B4=D1=8B=D0=B2=D0=B0=D0=BD?=
 =?UTF-8?q?=D0=B8=D0=B9=20=D0=B2=20=D0=BE=D0=BF=D1=86.=20=D0=BC=D0=BE?=
 =?UTF-8?q?=D0=B4=D0=B0=D1=85?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Жертвуя Tab-овским выбором чекбоксов.
Если кто придумает более элегантное решение - переделайте ;D
---
 Launcher/runtime/dialog/scenes/options/options.js | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Launcher/runtime/dialog/scenes/options/options.js b/Launcher/runtime/dialog/scenes/options/options.js
index b7749643..88fa0b9c 100644
--- a/Launcher/runtime/dialog/scenes/options/options.js
+++ b/Launcher/runtime/dialog/scenes/options/options.js
@@ -131,6 +131,7 @@ var options = {
                              }
                              options.update();
                          });
+                        testMod.setFocusTraversable(false);
                         checkBoxList.add(testMod);
                         testMod.getStyleClass().add("modname");
                          if(modDescription != "") {

From a0d6c5ad0efcbe18ff84fdca05b1ac21c5fab903 Mon Sep 17 00:00:00 2001
From: zaxar163 <zahar.vcherachny@yandex.ru>
Date: Fri, 31 May 2019 09:49:05 +0300
Subject: [PATCH 11/12] =?UTF-8?q?[FEATURE]=20=D0=A1=D0=B5=D1=80=D0=B8?=
 =?UTF-8?q?=D0=B0=D0=BB=D0=B8=D0=B7=D0=B0=D1=82=D0=BE=D1=80=20byte[]=20?=
 =?UTF-8?q?=D0=B2=20Base64?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../ru/gravit/utils/helper/CommonHelper.java  | 31 +++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/LauncherCore/src/main/java/ru/gravit/utils/helper/CommonHelper.java b/LauncherCore/src/main/java/ru/gravit/utils/helper/CommonHelper.java
index 5f7548e3..11e00272 100644
--- a/LauncherCore/src/main/java/ru/gravit/utils/helper/CommonHelper.java
+++ b/LauncherCore/src/main/java/ru/gravit/utils/helper/CommonHelper.java
@@ -6,6 +6,18 @@
 import javax.script.ScriptEngine;
 import javax.script.ScriptEngineFactory;
 import javax.script.ScriptEngineManager;
+
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonParseException;
+import com.google.gson.JsonPrimitive;
+import com.google.gson.JsonSerializationContext;
+import com.google.gson.JsonSerializer;
+
+import java.lang.reflect.Type;
+import java.util.Base64;
 import java.util.Collection;
 import java.util.LinkedList;
 import java.util.Locale;
@@ -120,4 +132,23 @@ public static String[] parseCommand(CharSequence line) throws CommandException {
         // Return result as array
         return result.toArray(new String[0]);
     }
+
+    @LauncherAPI
+    public static GsonBuilder newBuilder() {
+    	return new GsonBuilder().registerTypeHierarchyAdapter(byte[].class,
+                ByteArrayToBase64TypeAdapter.INSTANCE);
+    }
+
+    private static class ByteArrayToBase64TypeAdapter implements JsonSerializer<byte[]>, JsonDeserializer<byte[]> {
+    	private static final ByteArrayToBase64TypeAdapter INSTANCE = new ByteArrayToBase64TypeAdapter();
+    	private Base64.Decoder decoder = Base64.getUrlDecoder();
+    	private Base64.Encoder encoder = Base64.getUrlEncoder();
+    	public byte[] deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
+            return decoder.decode(json.getAsString());
+        }
+
+        public JsonElement serialize(byte[] src, Type typeOfSrc, JsonSerializationContext context) {
+            return new JsonPrimitive(encoder.encodeToString(src));
+        }
+    }
 }

From a1652eaf38b29c2a28bb9c43ceeea75e76b20568 Mon Sep 17 00:00:00 2001
From: zaxar163 <zahar.vcherachny@yandex.ru>
Date: Fri, 31 May 2019 10:02:56 +0300
Subject: [PATCH 12/12] =?UTF-8?q?[FEATURE][EXP]=20=D0=9F=D1=80=D0=B0=D0=B2?=
 =?UTF-8?q?=D0=B8=D0=BB=D1=8C=D0=BD=D0=BE=D0=B5=20=D1=81=D0=B5=D1=80=D0=B5?=
 =?UTF-8?q?=D0=B0=D0=BB=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D1=8F=20byte[]=20?=
 =?UTF-8?q?=D0=B2=20GsonManager.?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../main/java/ru/gravit/launcher/managers/GsonManager.java   | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/LauncherCore/src/main/java/ru/gravit/launcher/managers/GsonManager.java b/LauncherCore/src/main/java/ru/gravit/launcher/managers/GsonManager.java
index bf89bb33..bf93aafd 100644
--- a/LauncherCore/src/main/java/ru/gravit/launcher/managers/GsonManager.java
+++ b/LauncherCore/src/main/java/ru/gravit/launcher/managers/GsonManager.java
@@ -4,6 +4,7 @@
 import com.google.gson.GsonBuilder;
 import ru.gravit.launcher.hasher.HashedEntry;
 import ru.gravit.launcher.hasher.HashedEntryAdapter;
+import ru.gravit.utils.helper.CommonHelper;
 
 public class GsonManager {
     public GsonBuilder gsonBuilder;
@@ -12,8 +13,8 @@ public class GsonManager {
     public Gson configGson;
 
     public void initGson() {
-        gsonBuilder = new GsonBuilder();
-        configGsonBuilder = new GsonBuilder();
+        gsonBuilder = CommonHelper.newBuilder();
+        configGsonBuilder = CommonHelper.newBuilder();
         configGsonBuilder.setPrettyPrinting();
         registerAdapters(gsonBuilder);
         registerAdapters(configGsonBuilder);