wörk wörk
This commit is contained in:
parent
9e1509872a
commit
11bd1c8269
@ -28,15 +28,15 @@ while IFS= read -r line; do
|
|||||||
mustgenerate=false
|
mustgenerate=false
|
||||||
zsyncfile="${line}.zsync"
|
zsyncfile="${line}.zsync"
|
||||||
|
|
||||||
filebyte=$(wc -c < ${line})
|
filebyte=$(wc -c < "${line}")
|
||||||
filedate=$(stat -c %Y ${line})
|
filedate=$(stat -c %Y "${line}")
|
||||||
|
|
||||||
zsyncfiledate=$(strings ${zsyncfile} 2>/dev/null | grep -m 1 MTime | cut -d" " -f2-)
|
zsyncfiledate=$(strings "${zsyncfile}" 2>/dev/null | grep -m 1 MTime | cut -d" " -f2-)
|
||||||
|
|
||||||
if [ ! -f "$zsyncfile" ]; then
|
if [ ! -f "$zsyncfile" ]; then
|
||||||
echo "$zsyncfile does not exist"
|
echo "$zsyncfile does not exist"
|
||||||
mustgenerate=true
|
mustgenerate=true
|
||||||
elif [[ ! $(strings ${zsyncfile} | grep -m 1 Length | cut -d" " -f2) == $filebyte ]]; then # Check file length
|
elif [[ ! $(strings "${zsyncfile}" | grep -m 1 Length | cut -d" " -f2) == $filebyte ]]; then # Check file length
|
||||||
echo "$zsyncfile does not have corret length"
|
echo "$zsyncfile does not have corret length"
|
||||||
mustgenerate=true
|
mustgenerate=true
|
||||||
elif [[ ! $filedate == $(date -d "${zsyncfiledate}" +"%s") ]]; then # Check date
|
elif [[ ! $filedate == $(date -d "${zsyncfiledate}" +"%s") ]]; then # Check date
|
||||||
@ -46,11 +46,11 @@ while IFS= read -r line; do
|
|||||||
|
|
||||||
if [ "$mustgenerate" = true ]; then
|
if [ "$mustgenerate" = true ]; then
|
||||||
echo "Generate $zsyncfile"
|
echo "Generate $zsyncfile"
|
||||||
rm ${zsyncfile} 2> /dev/null
|
rm "${zsyncfile}" 2> /dev/null
|
||||||
dirfile=$(dirname ${line})
|
dirfile=$(dirname "${line}")
|
||||||
filename=$(basename ${line})
|
filename=$(basename "${line}")
|
||||||
filenamezsync=$(basename ${zsyncfile})
|
filenamezsync=$(basename "${zsyncfile}")
|
||||||
$(cd ${dirfile} && zsyncmake -o ${filenamezsync} ${filename})
|
$(cd "${dirfile}" && zsyncmake -o "${filenamezsync}" "${filename}")
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
echo "Success: Generated ${zsyncfile}"
|
echo "Success: Generated ${zsyncfile}"
|
||||||
else
|
else
|
||||||
@ -67,10 +67,10 @@ echo -e "===== ===== ===== ===== ===== =====\n"
|
|||||||
echo "===== ===== ===== DELETE SINGLE ZFILE WITHOUT FILE ===== ===== ====="
|
echo "===== ===== ===== DELETE SINGLE ZFILE WITHOUT FILE ===== ===== ====="
|
||||||
ZSYNCLIST=$(find . -name "*.zsync")
|
ZSYNCLIST=$(find . -name "*.zsync")
|
||||||
while IFS= read -r zfile; do
|
while IFS= read -r zfile; do
|
||||||
ORIG=$(echo ${zfile} | rev | cut -c7- | rev)
|
ORIG=$(echo "${zfile}" | rev | cut -c7- | rev)
|
||||||
if [ ! -f "$ORIG" ]; then
|
if [ ! -f "$ORIG" ]; then
|
||||||
echo "$ORIG does not exist"
|
echo "$ORIG does not exist"
|
||||||
rm ${zfile}
|
rm "${zfile}"
|
||||||
fi
|
fi
|
||||||
done <<< "$ZSYNCLIST"
|
done <<< "$ZSYNCLIST"
|
||||||
echo -e "===== ===== ===== ===== ===== =====\n"
|
echo -e "===== ===== ===== ===== ===== =====\n"
|
||||||
@ -85,18 +85,18 @@ while IFS= read -r folder; do
|
|||||||
echo "is dir"
|
echo "is dir"
|
||||||
x=""
|
x=""
|
||||||
foldersize=0
|
foldersize=0
|
||||||
FILEFOLDER=$(find ${folder} -type f ! -path "*.zsync" | sed 's|^./||')
|
FILEFOLDER=$(find "${folder}" -type f ! -path "*.zsync" | sed 's|^./||')
|
||||||
while IFS= read -r folderfile; do
|
while IFS= read -r folderfile; do
|
||||||
filebyte=$(wc -c < ${folderfile})
|
filebyte=$(wc -c < "${folderfile}")
|
||||||
foldersize=$(expr $foldersize + $filebyte)
|
foldersize=$(expr $foldersize + $filebyte)
|
||||||
name=$(echo ${folderfile} | cut -d"/" -f2-)
|
name=$(echo "${folderfile}" | cut -d"/" -f2-)
|
||||||
x="\"${name}\":${filebyte},${x}"
|
x="\"${name}\":${filebyte},${x}"
|
||||||
done <<< "$FILEFOLDER"
|
done <<< "$FILEFOLDER"
|
||||||
x=$(echo ${x} | rev | cut -c2- | rev)
|
x=$(echo ${x} | rev | cut -c2- | rev)
|
||||||
JSONDATA+=( "\"${folder}\": {\"size\":${foldersize},\"content\":{${x}}}" )
|
JSONDATA+=( "\"${folder}\": {\"size\":${foldersize},\"content\":{${x}}}" )
|
||||||
else
|
else
|
||||||
echo "is file"
|
echo "is file"
|
||||||
filebyte=$(wc -c < ${folder})
|
filebyte=$(wc -c < "${folder}")
|
||||||
JSONDATA+=( "\"${folder}\": {\"size\":${filebyte}}" )
|
JSONDATA+=( "\"${folder}\": {\"size\":${filebyte}}" )
|
||||||
fi
|
fi
|
||||||
done <<< "$FILELIST"
|
done <<< "$FILELIST"
|
||||||
|
5
pom.xml
5
pom.xml
@ -57,6 +57,11 @@
|
|||||||
<artifactId>zsyncer</artifactId>
|
<artifactId>zsyncer</artifactId>
|
||||||
<version>-f69d844481-1</version>
|
<version>-f69d844481-1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.squareup.okhttp3</groupId>
|
||||||
|
<artifactId>okhttp</artifactId>
|
||||||
|
<version>4.4.1</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@ -3,7 +3,6 @@ package de.mc8051.arma3launcher;
|
|||||||
import com.formdev.flatlaf.FlatDarkLaf;
|
import com.formdev.flatlaf.FlatDarkLaf;
|
||||||
import com.typesafe.config.Config;
|
import com.typesafe.config.Config;
|
||||||
import com.typesafe.config.ConfigFactory;
|
import com.typesafe.config.ConfigFactory;
|
||||||
import de.mc8051.arma3launcher.repo.RepositoryManger;
|
|
||||||
import de.mc8051.arma3launcher.steam.SteamTimer;
|
import de.mc8051.arma3launcher.steam.SteamTimer;
|
||||||
import org.ini4j.Ini;
|
import org.ini4j.Ini;
|
||||||
|
|
||||||
@ -12,7 +11,6 @@ import java.awt.*;
|
|||||||
import java.awt.event.WindowAdapter;
|
import java.awt.event.WindowAdapter;
|
||||||
import java.awt.event.WindowEvent;
|
import java.awt.event.WindowEvent;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Timer;
|
import java.util.Timer;
|
||||||
@ -81,7 +79,7 @@ public class ArmA3Launcher {
|
|||||||
frame.setLocationRelativeTo(null);
|
frame.setLocationRelativeTo(null);
|
||||||
|
|
||||||
steamTimer.scheduleAtFixedRate(
|
steamTimer.scheduleAtFixedRate(
|
||||||
new SteamTimer(gui),
|
new SteamTimer(),
|
||||||
500, // run first occurrence immediately
|
500, // run first occurrence immediately
|
||||||
10000); // run every thirty seconds
|
10000); // run every thirty seconds
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
<grid id="27dc6" binding="mainPanel" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
<grid id="27dc6" binding="mainPanel" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||||
<margin top="0" left="0" bottom="0" right="0"/>
|
<margin top="0" left="0" bottom="0" right="0"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<xy x="20" y="20" width="1048" height="542"/>
|
<xy x="20" y="20" width="1048" height="526"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<properties/>
|
<properties/>
|
||||||
<border type="none"/>
|
<border type="none"/>
|
||||||
@ -237,6 +237,7 @@
|
|||||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<properties>
|
<properties>
|
||||||
|
<enabled value="false"/>
|
||||||
<font size="18" style="1"/>
|
<font size="18" style="1"/>
|
||||||
<margin top="15" left="0" bottom="15" right="0"/>
|
<margin top="15" left="0" bottom="15" right="0"/>
|
||||||
<text resource-bundle="lang" key="play_now"/>
|
<text resource-bundle="lang" key="play_now"/>
|
||||||
@ -294,34 +295,73 @@
|
|||||||
</component>
|
</component>
|
||||||
</children>
|
</children>
|
||||||
</grid>
|
</grid>
|
||||||
<component id="113bf" class="javax.swing.JTree" binding="tree1" default-binding="true">
|
<grid id="74882" layout-manager="GridLayoutManager" row-count="3" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||||
<constraints border-constraint="Center"/>
|
|
||||||
<properties/>
|
|
||||||
</component>
|
|
||||||
<grid id="74882" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
|
||||||
<margin top="0" left="0" bottom="0" right="0"/>
|
<margin top="0" left="0" bottom="0" right="0"/>
|
||||||
<constraints border-constraint="South"/>
|
<constraints border-constraint="South"/>
|
||||||
<properties/>
|
<properties/>
|
||||||
<border type="none"/>
|
<border type="none"/>
|
||||||
<children>
|
<children>
|
||||||
<component id="f4a5" class="javax.swing.JButton" binding="allesAuswählenButton" default-binding="true">
|
<component id="13d22" class="javax.swing.JButton" binding="expandAllButton">
|
||||||
<constraints>
|
<constraints>
|
||||||
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<properties>
|
<properties>
|
||||||
<text resource-bundle="lang" key="select_all"/>
|
<enabled value="false"/>
|
||||||
|
<text resource-bundle="lang" key="expand_all"/>
|
||||||
</properties>
|
</properties>
|
||||||
</component>
|
</component>
|
||||||
<component id="13d22" class="javax.swing.JButton" binding="allesAusklappenButton" default-binding="true">
|
<component id="43543" class="javax.swing.JComboBox" binding="comboBox1" default-binding="true">
|
||||||
<constraints>
|
<constraints>
|
||||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
|
||||||
|
</constraints>
|
||||||
|
<properties/>
|
||||||
|
</component>
|
||||||
|
<component id="2b206" class="javax.swing.JLabel">
|
||||||
|
<constraints>
|
||||||
|
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="4" fill="0" indent="0" use-parent-layout="false"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<properties>
|
<properties>
|
||||||
<text resource-bundle="lang" key="expand_all"/>
|
<text resource-bundle="lang" key="preset"/>
|
||||||
|
</properties>
|
||||||
|
</component>
|
||||||
|
<component id="c9d68" class="javax.swing.JButton" binding="refreshRepoButton">
|
||||||
|
<constraints>
|
||||||
|
<grid row="2" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||||
|
</constraints>
|
||||||
|
<properties>
|
||||||
|
<enabled value="false"/>
|
||||||
|
<text resource-bundle="lang" key="update_repository"/>
|
||||||
|
</properties>
|
||||||
|
</component>
|
||||||
|
<component id="4ec7b" class="javax.swing.JButton" binding="collapseAllButton">
|
||||||
|
<constraints>
|
||||||
|
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||||
|
</constraints>
|
||||||
|
<properties>
|
||||||
|
<enabled value="false"/>
|
||||||
|
<text resource-bundle="lang" key="collapse_all"/>
|
||||||
</properties>
|
</properties>
|
||||||
</component>
|
</component>
|
||||||
</children>
|
</children>
|
||||||
</grid>
|
</grid>
|
||||||
|
<scrollpane id="56725" binding="updateTreeScrolPane">
|
||||||
|
<constraints border-constraint="Center"/>
|
||||||
|
<properties/>
|
||||||
|
<border type="none"/>
|
||||||
|
<children>
|
||||||
|
<grid id="44d39" binding="updateTreePanel" layout-manager="BorderLayout" hgap="0" vgap="0">
|
||||||
|
<constraints/>
|
||||||
|
<properties/>
|
||||||
|
<border type="none"/>
|
||||||
|
<children>
|
||||||
|
<component id="38143" class="javax.swing.JTree" binding="tree1" default-binding="true">
|
||||||
|
<constraints border-constraint="Center"/>
|
||||||
|
<properties/>
|
||||||
|
</component>
|
||||||
|
</children>
|
||||||
|
</grid>
|
||||||
|
</children>
|
||||||
|
</scrollpane>
|
||||||
</children>
|
</children>
|
||||||
</grid>
|
</grid>
|
||||||
<grid id="dc84b" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
<grid id="dc84b" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||||
@ -367,7 +407,7 @@
|
|||||||
</component>
|
</component>
|
||||||
</children>
|
</children>
|
||||||
</grid>
|
</grid>
|
||||||
<grid id="3b45c" layout-manager="GridLayoutManager" row-count="4" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
<grid id="3b45c" layout-manager="GridLayoutManager" row-count="6" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||||
<margin top="0" left="3" bottom="0" right="0"/>
|
<margin top="0" left="3" bottom="0" right="0"/>
|
||||||
<constraints border-constraint="Center"/>
|
<constraints border-constraint="Center"/>
|
||||||
<properties/>
|
<properties/>
|
||||||
@ -378,7 +418,7 @@
|
|||||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<properties>
|
<properties>
|
||||||
<text value="Label"/>
|
<text resource-bundle="lang" key="check_local_addons"/>
|
||||||
</properties>
|
</properties>
|
||||||
</component>
|
</component>
|
||||||
<hspacer id="f47e0">
|
<hspacer id="f47e0">
|
||||||
@ -386,27 +426,23 @@
|
|||||||
<grid row="0" column="2" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
<grid row="0" column="2" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
</hspacer>
|
</hspacer>
|
||||||
<vspacer id="5a5d2">
|
<component id="7b453" class="javax.swing.JLabel" binding="syncCheckStatusLabel">
|
||||||
<constraints>
|
|
||||||
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
|
||||||
</constraints>
|
|
||||||
</vspacer>
|
|
||||||
<component id="7b453" class="javax.swing.JLabel">
|
|
||||||
<constraints>
|
<constraints>
|
||||||
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<properties>
|
<properties>
|
||||||
<text value="Label"/>
|
<font style="2"/>
|
||||||
|
<text value=""/>
|
||||||
</properties>
|
</properties>
|
||||||
</component>
|
</component>
|
||||||
<component id="c7b6" class="javax.swing.JProgressBar" binding="progressBar1" default-binding="true">
|
<component id="c7b6" class="javax.swing.JProgressBar" binding="syncCheckProgress">
|
||||||
<constraints>
|
<constraints>
|
||||||
<grid row="1" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
<grid row="1" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<properties>
|
<properties>
|
||||||
<string value=""/>
|
<string value=""/>
|
||||||
<stringPainted value="true"/>
|
<stringPainted value="true"/>
|
||||||
<value value="50"/>
|
<value value="0"/>
|
||||||
</properties>
|
</properties>
|
||||||
</component>
|
</component>
|
||||||
<grid id="c1d6e" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
<grid id="c1d6e" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||||
@ -417,19 +453,21 @@
|
|||||||
<properties/>
|
<properties/>
|
||||||
<border type="none"/>
|
<border type="none"/>
|
||||||
<children>
|
<children>
|
||||||
<component id="c8876" class="javax.swing.JButton" binding="abbrechenButton" default-binding="true">
|
<component id="c8876" class="javax.swing.JButton" binding="syncCheckAbortButton">
|
||||||
<constraints>
|
<constraints>
|
||||||
<grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
<grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<properties>
|
<properties>
|
||||||
|
<enabled value="false"/>
|
||||||
<text resource-bundle="lang" key="abort"/>
|
<text resource-bundle="lang" key="abort"/>
|
||||||
</properties>
|
</properties>
|
||||||
</component>
|
</component>
|
||||||
<component id="d7e4b" class="javax.swing.JButton" binding="überprüfenButton" default-binding="true">
|
<component id="d7e4b" class="javax.swing.JButton" binding="syncCheckButton">
|
||||||
<constraints>
|
<constraints>
|
||||||
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<properties>
|
<properties>
|
||||||
|
<enabled value="false"/>
|
||||||
<text resource-bundle="lang" key="check"/>
|
<text resource-bundle="lang" key="check"/>
|
||||||
</properties>
|
</properties>
|
||||||
</component>
|
</component>
|
||||||
@ -440,6 +478,54 @@
|
|||||||
</hspacer>
|
</hspacer>
|
||||||
</children>
|
</children>
|
||||||
</grid>
|
</grid>
|
||||||
|
<component id="c97ef" class="javax.swing.JLabel">
|
||||||
|
<constraints>
|
||||||
|
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||||
|
</constraints>
|
||||||
|
<properties>
|
||||||
|
<text resource-bundle="lang" key="changed_files"/>
|
||||||
|
</properties>
|
||||||
|
</component>
|
||||||
|
<component id="22374" class="javax.swing.JLabel">
|
||||||
|
<constraints>
|
||||||
|
<grid row="4" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||||
|
</constraints>
|
||||||
|
<properties>
|
||||||
|
<text resource-bundle="lang" key="added_files"/>
|
||||||
|
</properties>
|
||||||
|
</component>
|
||||||
|
<component id="e3c92" class="javax.swing.JLabel">
|
||||||
|
<constraints>
|
||||||
|
<grid row="5" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||||
|
</constraints>
|
||||||
|
<properties>
|
||||||
|
<text resource-bundle="lang" key="deleted_files"/>
|
||||||
|
</properties>
|
||||||
|
</component>
|
||||||
|
<component id="16f6a" class="javax.swing.JLabel" binding="syncChangedFilesLabel">
|
||||||
|
<constraints>
|
||||||
|
<grid row="3" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||||
|
</constraints>
|
||||||
|
<properties>
|
||||||
|
<text value="0"/>
|
||||||
|
</properties>
|
||||||
|
</component>
|
||||||
|
<component id="929a5" class="javax.swing.JLabel" binding="syncAddedFilesLabel">
|
||||||
|
<constraints>
|
||||||
|
<grid row="4" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||||
|
</constraints>
|
||||||
|
<properties>
|
||||||
|
<text value="0"/>
|
||||||
|
</properties>
|
||||||
|
</component>
|
||||||
|
<component id="f6ef3" class="javax.swing.JLabel" binding="syncDeletedFilesLabel">
|
||||||
|
<constraints>
|
||||||
|
<grid row="5" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||||
|
</constraints>
|
||||||
|
<properties>
|
||||||
|
<text value="0"/>
|
||||||
|
</properties>
|
||||||
|
</component>
|
||||||
</children>
|
</children>
|
||||||
</grid>
|
</grid>
|
||||||
</children>
|
</children>
|
||||||
@ -516,7 +602,7 @@
|
|||||||
<text resource-bundle="lang" key="remaining_time"/>
|
<text resource-bundle="lang" key="remaining_time"/>
|
||||||
</properties>
|
</properties>
|
||||||
</component>
|
</component>
|
||||||
<component id="b28b6" class="javax.swing.JLabel">
|
<component id="b28b6" class="javax.swing.JLabel" binding="syncSizeLabel">
|
||||||
<constraints>
|
<constraints>
|
||||||
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
@ -613,27 +699,30 @@
|
|||||||
<properties/>
|
<properties/>
|
||||||
<border type="none"/>
|
<border type="none"/>
|
||||||
<children>
|
<children>
|
||||||
<component id="a5494" class="javax.swing.JButton" binding="downloadButton" default-binding="true">
|
<component id="a5494" class="javax.swing.JButton" binding="syncDownloadButton">
|
||||||
<constraints>
|
<constraints>
|
||||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<properties>
|
<properties>
|
||||||
|
<enabled value="false"/>
|
||||||
<text resource-bundle="lang" key="download"/>
|
<text resource-bundle="lang" key="download"/>
|
||||||
</properties>
|
</properties>
|
||||||
</component>
|
</component>
|
||||||
<component id="f8be1" class="javax.swing.JButton" binding="abbrechenButton1" default-binding="true">
|
<component id="f8be1" class="javax.swing.JButton" binding="syncDownloadAbortButton">
|
||||||
<constraints>
|
<constraints>
|
||||||
<grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
<grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<properties>
|
<properties>
|
||||||
|
<enabled value="false"/>
|
||||||
<text resource-bundle="lang" key="abort"/>
|
<text resource-bundle="lang" key="abort"/>
|
||||||
</properties>
|
</properties>
|
||||||
</component>
|
</component>
|
||||||
<component id="c94f5" class="javax.swing.JButton" binding="pauseButton" default-binding="true">
|
<component id="c94f5" class="javax.swing.JButton" binding="syncPauseButton">
|
||||||
<constraints>
|
<constraints>
|
||||||
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<properties>
|
<properties>
|
||||||
|
<enabled value="false"/>
|
||||||
<text resource-bundle="lang" key="pause"/>
|
<text resource-bundle="lang" key="pause"/>
|
||||||
</properties>
|
</properties>
|
||||||
</component>
|
</component>
|
||||||
@ -690,6 +779,7 @@
|
|||||||
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<properties>
|
<properties>
|
||||||
|
<enabled value="false"/>
|
||||||
<text resource-bundle="lang" key="play"/>
|
<text resource-bundle="lang" key="play"/>
|
||||||
</properties>
|
</properties>
|
||||||
</component>
|
</component>
|
||||||
@ -1079,6 +1169,7 @@
|
|||||||
</constraints>
|
</constraints>
|
||||||
<properties>
|
<properties>
|
||||||
<text value="SkipIntro"/>
|
<text value="SkipIntro"/>
|
||||||
|
<toolTipText resource-bundle="lang" key="skipintro_desc"/>
|
||||||
</properties>
|
</properties>
|
||||||
</component>
|
</component>
|
||||||
<component id="435dd" class="javax.swing.JLabel">
|
<component id="435dd" class="javax.swing.JLabel">
|
||||||
|
@ -1,13 +1,19 @@
|
|||||||
package de.mc8051.arma3launcher;
|
package de.mc8051.arma3launcher;
|
||||||
|
|
||||||
import de.mc8051.arma3launcher.interfaces.Observer;
|
import de.mc8051.arma3launcher.interfaces.Observer;
|
||||||
|
import de.mc8051.arma3launcher.model.JCheckBoxTree;
|
||||||
import de.mc8051.arma3launcher.model.ModListRenderer;
|
import de.mc8051.arma3launcher.model.ModListRenderer;
|
||||||
import de.mc8051.arma3launcher.model.PresetListRenderer;
|
import de.mc8051.arma3launcher.model.PresetListRenderer;
|
||||||
import de.mc8051.arma3launcher.model.PresetTableModel;
|
import de.mc8051.arma3launcher.model.PresetTableModel;
|
||||||
import de.mc8051.arma3launcher.model.ServerTableModel;
|
import de.mc8051.arma3launcher.model.ServerTableModel;
|
||||||
|
import de.mc8051.arma3launcher.objects.AbstractMod;
|
||||||
|
import de.mc8051.arma3launcher.objects.Mod;
|
||||||
|
import de.mc8051.arma3launcher.objects.ModFile;
|
||||||
import de.mc8051.arma3launcher.objects.Modset;
|
import de.mc8051.arma3launcher.objects.Modset;
|
||||||
import de.mc8051.arma3launcher.objects.Server;
|
import de.mc8051.arma3launcher.objects.Server;
|
||||||
|
import de.mc8051.arma3launcher.repo.FileChecker;
|
||||||
import de.mc8051.arma3launcher.repo.RepositoryManger;
|
import de.mc8051.arma3launcher.repo.RepositoryManger;
|
||||||
|
import de.mc8051.arma3launcher.steam.SteamTimer;
|
||||||
import de.mc8051.arma3launcher.utils.Callback;
|
import de.mc8051.arma3launcher.utils.Callback;
|
||||||
import de.mc8051.arma3launcher.utils.LangUtils;
|
import de.mc8051.arma3launcher.utils.LangUtils;
|
||||||
|
|
||||||
@ -16,6 +22,9 @@ import javax.swing.event.ListSelectionEvent;
|
|||||||
import javax.swing.event.ListSelectionListener;
|
import javax.swing.event.ListSelectionListener;
|
||||||
import javax.swing.plaf.basic.BasicTabbedPaneUI;
|
import javax.swing.plaf.basic.BasicTabbedPaneUI;
|
||||||
import javax.swing.text.DefaultFormatter;
|
import javax.swing.text.DefaultFormatter;
|
||||||
|
import javax.swing.tree.DefaultMutableTreeNode;
|
||||||
|
import javax.swing.tree.DefaultTreeModel;
|
||||||
|
import javax.swing.tree.TreePath;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
@ -28,6 +37,11 @@ import java.net.URLDecoder;
|
|||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
@ -97,25 +111,50 @@ public class LauncherGUI implements Observer {
|
|||||||
private JScrollPane settingScrollPane;
|
private JScrollPane settingScrollPane;
|
||||||
private JCheckBox settingsUseWorkshopBox;
|
private JCheckBox settingsUseWorkshopBox;
|
||||||
private JTree tree1;
|
private JTree tree1;
|
||||||
private JButton allesAuswählenButton;
|
private JButton expandAllButton;
|
||||||
private JButton allesAusklappenButton;
|
private JProgressBar syncCheckProgress;
|
||||||
private JProgressBar progressBar1;
|
private JButton syncCheckAbortButton;
|
||||||
private JButton abbrechenButton;
|
private JButton syncCheckButton;
|
||||||
private JButton überprüfenButton;
|
|
||||||
private JProgressBar progressBar2;
|
private JProgressBar progressBar2;
|
||||||
private JProgressBar progressBar3;
|
private JProgressBar progressBar3;
|
||||||
private JButton downloadButton;
|
private JButton syncDownloadButton;
|
||||||
private JButton abbrechenButton1;
|
private JButton syncDownloadAbortButton;
|
||||||
private JButton pauseButton;
|
private JButton syncPauseButton;
|
||||||
|
private JComboBox comboBox1;
|
||||||
|
private JButton refreshRepoButton;
|
||||||
|
private JPanel updateTreePanel;
|
||||||
|
private JScrollPane updateTreeScrolPane;
|
||||||
|
private JButton collapseAllButton;
|
||||||
|
private JLabel syncCheckStatusLabel;
|
||||||
|
private JLabel syncDeletedFilesLabel;
|
||||||
|
private JLabel syncAddedFilesLabel;
|
||||||
|
private JLabel syncChangedFilesLabel;
|
||||||
|
private JLabel syncSizeLabel;
|
||||||
|
|
||||||
|
private JCheckBoxTree repoTree;
|
||||||
|
private FileChecker fileChecker;
|
||||||
|
|
||||||
// TODO: Updater
|
// TODO: Updater
|
||||||
/*
|
/*
|
||||||
Prüfung
|
Prüfung
|
||||||
In eine Liste hinzufügen wenn Datei in modset.json (Neu runterladen), nicht in modset.json (zum Löschen) oder die Größe unterschiedlich ist (Geändert)
|
In eine Liste hinzufügen wenn Datei in modset.json (Neu runterladen), nicht in modset.json (zum Löschen) oder die Größe unterschiedlich ist (Geändert)
|
||||||
|
Checkboxen beim Syncronisieren deaktivieren
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public LauncherGUI() {
|
public LauncherGUI() {
|
||||||
|
fileChecker = new FileChecker(syncCheckProgress);
|
||||||
|
|
||||||
RepositoryManger.getInstance().addObserver(this);
|
RepositoryManger.getInstance().addObserver(this);
|
||||||
|
SteamTimer.addObserver(this);
|
||||||
|
fileChecker.addObserver(this);
|
||||||
|
|
||||||
|
updateTreePanel.remove(tree1);
|
||||||
|
|
||||||
|
repoTree = new JCheckBoxTree();
|
||||||
|
updateTreePanel.add(repoTree, BorderLayout.CENTER);
|
||||||
|
|
||||||
|
updateTreePanel.revalidate();
|
||||||
|
updateTreePanel.repaint();
|
||||||
|
|
||||||
tabbedPane1.setUI(new BasicTabbedPaneUI() {
|
tabbedPane1.setUI(new BasicTabbedPaneUI() {
|
||||||
private final Insets borderInsets = new Insets(0, 0, 0, 0);
|
private final Insets borderInsets = new Insets(0, 0, 0, 0);
|
||||||
@ -184,7 +223,7 @@ public class LauncherGUI implements Observer {
|
|||||||
Modset modset = (Modset) m.getElementAt(presetList.getSelectedIndex());
|
Modset modset = (Modset) m.getElementAt(presetList.getSelectedIndex());
|
||||||
System.out.println(modset.getName());
|
System.out.println(modset.getName());
|
||||||
|
|
||||||
if(modset.getType() == Modset.Type.SERVER) {
|
if (modset.getType() == Modset.Type.SERVER) {
|
||||||
renamePresetButton.setEnabled(false);
|
renamePresetButton.setEnabled(false);
|
||||||
removePresetButtom.setEnabled(false);
|
removePresetButtom.setEnabled(false);
|
||||||
} else {
|
} else {
|
||||||
@ -226,8 +265,45 @@ public class LauncherGUI implements Observer {
|
|||||||
});
|
});
|
||||||
|
|
||||||
settingScrollPane.getVerticalScrollBar().setUnitIncrement(16);
|
settingScrollPane.getVerticalScrollBar().setUnitIncrement(16);
|
||||||
|
updateTreeScrolPane.getVerticalScrollBar().setUnitIncrement(16);
|
||||||
|
|
||||||
RepositoryManger.getInstance().refreshMeta();
|
refreshRepoButton.addActionListener(e -> RepositoryManger.getInstance().refreshModset());
|
||||||
|
expandAllButton.addActionListener(new ActionListener() {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
repoTree.expandAllNodes();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
collapseAllButton.addActionListener(new ActionListener() {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
repoTree.collapseAllNodes();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
new Thread(() -> {
|
||||||
|
RepositoryManger.getInstance().refreshMeta();
|
||||||
|
RepositoryManger.getInstance().refreshModset();
|
||||||
|
}).start();
|
||||||
|
|
||||||
|
syncCheckButton.addActionListener(new ActionListener() {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
syncCheckButton.setEnabled(false);
|
||||||
|
syncCheckAbortButton.setEnabled(true);
|
||||||
|
syncCheckStatusLabel.setText("Running!");
|
||||||
|
new Thread(() -> fileChecker.check()).start();
|
||||||
|
|
||||||
|
// TODO: disable JTree Checkboxes
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
syncCheckAbortButton.addActionListener(new ActionListener() {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
fileChecker.stop();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void infoBox(String infoMessage, String titleBar) {
|
public static void infoBox(String infoMessage, String titleBar) {
|
||||||
@ -261,9 +337,53 @@ public class LauncherGUI implements Observer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void techCheck() {
|
public void techCheck() {
|
||||||
// Arma Path set
|
boolean pathSet = ArmA3Launcher.user_config.get("client").containsKey("armaPath") && ArmA3Launcher.user_config.get("client").containsKey("modPath");
|
||||||
// Steam running
|
if (SteamTimer.arma_running) {
|
||||||
// Arma not running
|
playButton.setEnabled(false);
|
||||||
|
playPresetButton.setEnabled(false);
|
||||||
|
syncCheckButton.setEnabled(false);
|
||||||
|
refreshRepoButton.setEnabled(false);
|
||||||
|
|
||||||
|
playButton.setToolTipText(LangUtils.getInstance().getString("arma_running"));
|
||||||
|
playPresetButton.setToolTipText(LangUtils.getInstance().getString("arma_running"));
|
||||||
|
syncCheckButton.setToolTipText(LangUtils.getInstance().getString("arma_running"));
|
||||||
|
} else {
|
||||||
|
if (SteamTimer.steam_running) {
|
||||||
|
if (pathSet) {
|
||||||
|
playButton.setEnabled(true);
|
||||||
|
playPresetButton.setEnabled(true);
|
||||||
|
|
||||||
|
playButton.setToolTipText(null);
|
||||||
|
playPresetButton.setToolTipText(null);
|
||||||
|
} else {
|
||||||
|
playButton.setEnabled(false);
|
||||||
|
playPresetButton.setEnabled(false);
|
||||||
|
|
||||||
|
playButton.setToolTipText(LangUtils.getInstance().getString("path_not_set"));
|
||||||
|
playPresetButton.setToolTipText(LangUtils.getInstance().getString("path_not_set"));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
playButton.setEnabled(false);
|
||||||
|
playPresetButton.setEnabled(false);
|
||||||
|
|
||||||
|
playButton.setToolTipText(LangUtils.getInstance().getString("steam_not_running"));
|
||||||
|
playPresetButton.setToolTipText(LangUtils.getInstance().getString("steam_not_running"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pathSet) {
|
||||||
|
syncCheckButton.setEnabled(true);
|
||||||
|
refreshRepoButton.setEnabled(true);
|
||||||
|
|
||||||
|
syncCheckButton.setToolTipText(null);
|
||||||
|
refreshRepoButton.setToolTipText(null);
|
||||||
|
} else {
|
||||||
|
syncCheckButton.setEnabled(true);
|
||||||
|
refreshRepoButton.setEnabled(true);
|
||||||
|
|
||||||
|
syncCheckButton.setToolTipText(LangUtils.getInstance().getString("path_not_set"));
|
||||||
|
refreshRepoButton.setToolTipText(LangUtils.getInstance().getString("path_not_set"));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean checkArmaPath(String path) {
|
public boolean checkArmaPath(String path) {
|
||||||
@ -318,7 +438,15 @@ public class LauncherGUI implements Observer {
|
|||||||
SwingUtilities.invokeLater(() -> warnBox(LangUtils.getInstance().getString("not_arma_dir_msg"), LangUtils.getInstance().getString("not_arma_dir")));
|
SwingUtilities.invokeLater(() -> warnBox(LangUtils.getInstance().getString("not_arma_dir_msg"), LangUtils.getInstance().getString("not_arma_dir")));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String modPath = ArmA3Launcher.user_config.get("client", "modPath");
|
||||||
|
if(sPath.equalsIgnoreCase(modPath)) {
|
||||||
|
SwingUtilities.invokeLater(() -> errorBox(LangUtils.getInstance().getString("same_mod_arma_dir_msg"), LangUtils.getInstance().getString("same_mod_arma_dir")));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
settingsArmaPathText.setText(sPath);
|
settingsArmaPathText.setText(sPath);
|
||||||
|
techCheck();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -326,7 +454,16 @@ public class LauncherGUI implements Observer {
|
|||||||
initFolderChooser(settingsModsPathText, settingsModsPathBtn, "modPath", Parameter.ParameterType.CLIENT, new Callback.JFileSelectCallback() {
|
initFolderChooser(settingsModsPathText, settingsModsPathBtn, "modPath", Parameter.ParameterType.CLIENT, new Callback.JFileSelectCallback() {
|
||||||
@Override
|
@Override
|
||||||
public boolean allowSelection(File path) {
|
public boolean allowSelection(File path) {
|
||||||
settingsModsPathText.setText(path.getAbsolutePath());
|
String sPath = path.getAbsolutePath();
|
||||||
|
|
||||||
|
String armaPath = ArmA3Launcher.user_config.get("client", "armaPath");
|
||||||
|
if(sPath.equalsIgnoreCase(armaPath)) {
|
||||||
|
SwingUtilities.invokeLater(() -> errorBox(LangUtils.getInstance().getString("same_mod_arma_dir_msg"), LangUtils.getInstance().getString("same_mod_arma_dir")));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
settingsModsPathText.setText(sPath);
|
||||||
|
RepositoryManger.getInstance().refreshModset();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -413,9 +550,73 @@ public class LauncherGUI implements Observer {
|
|||||||
spinner.addChangeListener(new SettingsHandler.SpinnerListener(paraObj));
|
spinner.addChangeListener(new SettingsHandler.SpinnerListener(paraObj));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ArrayList<AbstractMod> getSyncList() {
|
||||||
|
ArrayList<AbstractMod> modList = new ArrayList<>();
|
||||||
|
|
||||||
|
HashMap<String, ArrayList<String>> tempMap = new HashMap<>();
|
||||||
|
for (TreePath checkedPath : repoTree.getCheckedPaths()) {
|
||||||
|
DefaultMutableTreeNode tn = (DefaultMutableTreeNode)checkedPath.getLastPathComponent();
|
||||||
|
|
||||||
|
if(tn.getChildCount() > 0) continue;
|
||||||
|
Object[] path = checkedPath.getPath();
|
||||||
|
DefaultMutableTreeNode[] modifiedArray = Arrays.stream(Arrays.copyOfRange(path, 1, path.length)).toArray(DefaultMutableTreeNode[]::new);
|
||||||
|
|
||||||
|
ArrayList<String> strings = new ArrayList<>();
|
||||||
|
if(tempMap.containsKey(String.valueOf(modifiedArray[0].getUserObject()))) {
|
||||||
|
strings = tempMap.get(String.valueOf(modifiedArray[0].getUserObject()));
|
||||||
|
}
|
||||||
|
|
||||||
|
String modPath = "";
|
||||||
|
for (int i = 1; i < modifiedArray.length; i++) {
|
||||||
|
modPath += String.valueOf(modifiedArray[i].getUserObject()) + "/";
|
||||||
|
}
|
||||||
|
modPath = modPath.isEmpty() ? "" : modPath.substring(0, modPath.length() - 1);
|
||||||
|
strings.add(modPath);
|
||||||
|
|
||||||
|
tempMap.put((String) modifiedArray[0].getUserObject(), strings);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Map.Entry<String, ArrayList<String>> entry : tempMap.entrySet()) {
|
||||||
|
String modS = entry.getKey();
|
||||||
|
ArrayList<String> modlistS = entry.getValue();
|
||||||
|
|
||||||
|
if(modlistS.isEmpty()) {
|
||||||
|
for (AbstractMod abstractMod : RepositoryManger.MOD_LIST) {
|
||||||
|
if (abstractMod.getName().equals(modS)) {
|
||||||
|
modList.add(abstractMod);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (AbstractMod abstractMod : RepositoryManger.MOD_LIST) {
|
||||||
|
if (abstractMod.getName().equals(modS)) {
|
||||||
|
if(!(abstractMod instanceof Mod)) continue;
|
||||||
|
Mod m = ((Mod) abstractMod).clone();
|
||||||
|
|
||||||
|
for (int i = 0; i < m.getFiles().size(); i++) {
|
||||||
|
boolean found = false;
|
||||||
|
for (String pathS : modlistS) {
|
||||||
|
if(m.getFiles().get(i).getModfileString().equals(pathS)) {
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!found) {
|
||||||
|
m.getFiles().remove(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
modList.add(m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return modList;
|
||||||
|
}
|
||||||
|
|
||||||
public void updateModList(Modset modset) {
|
public void updateModList(Modset modset) {
|
||||||
ListModel<String> model = (ListModel)modList.getModel();
|
ListModel<String> model = (ListModel) modList.getModel();
|
||||||
// TODO: RepositoryManger.downloadModlist
|
|
||||||
// TODO: Show All Mods (keyname)
|
// TODO: Show All Mods (keyname)
|
||||||
// TODO: Show not installed Mods with red font
|
// TODO: Show not installed Mods with red font
|
||||||
// TODO: Select Mod if in modset.Mods
|
// TODO: Select Mod if in modset.Mods
|
||||||
@ -423,27 +624,184 @@ public class LauncherGUI implements Observer {
|
|||||||
// TODO: Wenn modset.type == Server alle Checkboxen deaktivieren!
|
// TODO: Wenn modset.type == Server alle Checkboxen deaktivieren!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void updateRepoTree() {
|
||||||
|
expandAllButton.setEnabled(false);
|
||||||
|
collapseAllButton.setEnabled(false);
|
||||||
|
|
||||||
|
DefaultTreeModel model = (DefaultTreeModel) repoTree.getModel();
|
||||||
|
DefaultMutableTreeNode root = (DefaultMutableTreeNode) model.getRoot();
|
||||||
|
root.setUserObject("Repository");
|
||||||
|
root.removeAllChildren();
|
||||||
|
|
||||||
|
for (AbstractMod abstractMod : RepositoryManger.MOD_LIST) {
|
||||||
|
if (abstractMod instanceof Mod) {
|
||||||
|
// Whole Folder
|
||||||
|
// TODO: Recursives Ordner Parsen und einzelne Treenodes erstellen
|
||||||
|
Mod m = (Mod) abstractMod;
|
||||||
|
DefaultMutableTreeNode modFolder = new DefaultMutableTreeNode(m.getName(), true);
|
||||||
|
model.insertNodeInto(modFolder, root, root.getChildCount());
|
||||||
|
|
||||||
|
for (ModFile modfile : m.getFiles()) {
|
||||||
|
|
||||||
|
DefaultMutableTreeNode lastNode = modFolder;
|
||||||
|
ArrayList<String> path = modfile.getPath();
|
||||||
|
|
||||||
|
for (int i = 0; i < path.size(); i++) {
|
||||||
|
boolean found = false;
|
||||||
|
|
||||||
|
for (int j = 0; j < lastNode.getChildCount(); j++) {
|
||||||
|
DefaultMutableTreeNode temp = (DefaultMutableTreeNode) lastNode.getChildAt(j);
|
||||||
|
if (temp.getUserObject().equals(path.get(i))) {
|
||||||
|
found = true;
|
||||||
|
lastNode = temp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
DefaultMutableTreeNode temp = new DefaultMutableTreeNode(path.get(i));
|
||||||
|
model.insertNodeInto(temp, lastNode, lastNode.getChildCount());
|
||||||
|
lastNode = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
model.insertNodeInto(new DefaultMutableTreeNode(modfile.getName()), lastNode, lastNode.getChildCount());
|
||||||
|
}
|
||||||
|
sort(modFolder);
|
||||||
|
} else if (abstractMod instanceof ModFile) {
|
||||||
|
// Just a Single FIle
|
||||||
|
ModFile m = (ModFile) abstractMod;
|
||||||
|
model.insertNodeInto(new DefaultMutableTreeNode(m.getName(), false), root, root.getChildCount());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sort(root);
|
||||||
|
|
||||||
|
repoTree.clearCheckChangeEventListeners();
|
||||||
|
|
||||||
|
repoTree.resetCheckingState();
|
||||||
|
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
model.nodeChanged(root);
|
||||||
|
model.reload();
|
||||||
|
repoTree.revalidate();
|
||||||
|
repoTree.repaint();
|
||||||
|
updateTreePanel.revalidate();
|
||||||
|
updateTreePanel.repaint();
|
||||||
|
});
|
||||||
|
|
||||||
|
expandAllButton.setEnabled(true);
|
||||||
|
collapseAllButton.setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DefaultMutableTreeNode sort(DefaultMutableTreeNode node) {
|
||||||
|
|
||||||
|
//sort alphabetically
|
||||||
|
for(int i = 0; i < node.getChildCount() - 1; i++) {
|
||||||
|
DefaultMutableTreeNode child = (DefaultMutableTreeNode) node.getChildAt(i);
|
||||||
|
String nt = child.getUserObject().toString();
|
||||||
|
|
||||||
|
for(int j = i + 1; j <= node.getChildCount() - 1; j++) {
|
||||||
|
DefaultMutableTreeNode prevNode = (DefaultMutableTreeNode) node.getChildAt(j);
|
||||||
|
String np = prevNode.getUserObject().toString();
|
||||||
|
|
||||||
|
if(nt.compareToIgnoreCase(np) > 0) {
|
||||||
|
node.insert(child, j);
|
||||||
|
node.insert(prevNode, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(child.getChildCount() > 0) {
|
||||||
|
sort(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//put folders first - normal on Windows and some flavors of Linux but not on Mac OS X.
|
||||||
|
for(int i = 0; i < node.getChildCount() - 1; i++) {
|
||||||
|
DefaultMutableTreeNode child = (DefaultMutableTreeNode) node.getChildAt(i);
|
||||||
|
for(int j = i + 1; j <= node.getChildCount() - 1; j++) {
|
||||||
|
DefaultMutableTreeNode prevNode = (DefaultMutableTreeNode) node.getChildAt(j);
|
||||||
|
|
||||||
|
if(!prevNode.isLeaf() && child.isLeaf()) {
|
||||||
|
node.insert(child, j);
|
||||||
|
node.insert(prevNode, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(Object o) {
|
public void update(String s) {
|
||||||
String s = String.valueOf(o);
|
System.out.println(s);
|
||||||
|
if (s.equals(RepositoryManger.Type.METADATA.toString())) {
|
||||||
|
switch (RepositoryManger.getInstance().getStatus(RepositoryManger.Type.METADATA)) {
|
||||||
|
case ERROR:
|
||||||
|
errorBox("Metadata download failed. Is the server availaible? Do you have an active internet connection?", "Download failed");
|
||||||
|
System.exit(1);
|
||||||
|
break;
|
||||||
|
|
||||||
if (s.equals("refreshMeta")) {
|
case FINNISHED:
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
ServerTableModel model = (ServerTableModel) serverTable.getModel();
|
||||||
|
|
||||||
|
Server.SERVER_LIST.forEach((name, server) -> model.add(server));
|
||||||
|
});
|
||||||
|
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
PresetTableModel model = (PresetTableModel) presetList.getModel();
|
||||||
|
model.clear();
|
||||||
|
|
||||||
|
model.add(new Modset("--Server", Modset.Type.CLIENT, null, false));
|
||||||
|
|
||||||
|
Modset.MODSET_LIST.forEach((name, set) -> {
|
||||||
|
model.add(set);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (s.equals("steamtimer")) {
|
||||||
SwingUtilities.invokeLater(() -> {
|
SwingUtilities.invokeLater(() -> {
|
||||||
ServerTableModel model = (ServerTableModel) serverTable.getModel();
|
updateLabels(SteamTimer.steam_running, SteamTimer.arma_running);
|
||||||
|
techCheck();
|
||||||
Server.SERVER_LIST.forEach((name, server) -> model.add(server));
|
|
||||||
});
|
});
|
||||||
|
} else if (s.equals(RepositoryManger.Type.MODSET.toString())) {
|
||||||
|
switch (RepositoryManger.getInstance().getStatus(RepositoryManger.Type.METADATA)) {
|
||||||
|
case FINNISHED:
|
||||||
|
refreshRepoButton.setEnabled(true);
|
||||||
|
updateRepoTree();
|
||||||
|
break;
|
||||||
|
|
||||||
SwingUtilities.invokeLater(() -> {
|
case RUNNING:
|
||||||
PresetTableModel model = (PresetTableModel) presetList.getModel();
|
refreshRepoButton.setEnabled(false);
|
||||||
model.clear();
|
break;
|
||||||
|
}
|
||||||
|
} else if(s.equals("fileChecker")) {
|
||||||
|
syncCheckButton.setEnabled(true);
|
||||||
|
syncCheckAbortButton.setEnabled(false);
|
||||||
|
syncCheckStatusLabel.setText("Finished!");
|
||||||
|
updateRepoTree();
|
||||||
|
// TODO: Label einfärben
|
||||||
|
// TODO: Enable Tree Checkboxes
|
||||||
|
syncDownloadButton.setEnabled(true);
|
||||||
|
syncAddedFilesLabel.setText(String.valueOf(fileChecker.getAddedCount()));
|
||||||
|
syncChangedFilesLabel.setText(String.valueOf(fileChecker.getChangedCount()));
|
||||||
|
syncDeletedFilesLabel.setText(String.valueOf(fileChecker.getDeletedCount()));
|
||||||
|
|
||||||
model.add(new Modset("--Server", Modset.Type.CLIENT, null, false));
|
syncSizeLabel.setText(String.valueOf(fileChecker.getSize())); // TODO: Make Humanreadable
|
||||||
|
} else if (s.equals("fileCheckerStopped")) {
|
||||||
|
syncCheckButton.setEnabled(true);
|
||||||
|
syncCheckAbortButton.setEnabled(false);
|
||||||
|
syncCheckProgress.setValue(0);
|
||||||
|
syncCheckStatusLabel.setText("Failed!");
|
||||||
|
|
||||||
Modset.MODSET_LIST.forEach((name, set) -> {
|
syncAddedFilesLabel.setText("" + 0);
|
||||||
model.add(set);
|
syncChangedFilesLabel.setText("" + 0);
|
||||||
});
|
syncDeletedFilesLabel.setText("" + 0);
|
||||||
});
|
|
||||||
|
syncSizeLabel.setText("0.0 B");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,5 +7,5 @@ public interface Observable {
|
|||||||
|
|
||||||
public void addObserver(Observer observer);
|
public void addObserver(Observer observer);
|
||||||
public void removeObserver(Observer observer);
|
public void removeObserver(Observer observer);
|
||||||
public void notifyObservers(Object obj);
|
public void notifyObservers(String obj);
|
||||||
}
|
}
|
||||||
|
@ -5,5 +5,5 @@ package de.mc8051.arma3launcher.interfaces;
|
|||||||
*/
|
*/
|
||||||
public interface Observer {
|
public interface Observer {
|
||||||
|
|
||||||
public void update(Object o);
|
public void update(String o);
|
||||||
}
|
}
|
||||||
|
295
src/main/java/de/mc8051/arma3launcher/model/JCheckBoxTree.java
Normal file
295
src/main/java/de/mc8051/arma3launcher/model/JCheckBoxTree.java
Normal file
@ -0,0 +1,295 @@
|
|||||||
|
package de.mc8051.arma3launcher.model;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.event.EventListenerList;
|
||||||
|
import javax.swing.tree.DefaultMutableTreeNode;
|
||||||
|
import javax.swing.tree.DefaultTreeSelectionModel;
|
||||||
|
import javax.swing.tree.TreeCellRenderer;
|
||||||
|
import javax.swing.tree.TreeModel;
|
||||||
|
import javax.swing.tree.TreeNode;
|
||||||
|
import javax.swing.tree.TreePath;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.MouseEvent;
|
||||||
|
import java.awt.event.MouseListener;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.EventListener;
|
||||||
|
import java.util.EventObject;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by SomethingSomething https://stackoverflow.com/a/21851201/5605489
|
||||||
|
*/
|
||||||
|
public class JCheckBoxTree extends JTree {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -4194122328392241790L;
|
||||||
|
|
||||||
|
JCheckBoxTree selfPointer = this;
|
||||||
|
|
||||||
|
|
||||||
|
// Defining data structure that will enable to fast check-indicate the state of each node
|
||||||
|
// It totally replaces the "selection" mechanism of the JTree
|
||||||
|
private class CheckedNode {
|
||||||
|
boolean isSelected;
|
||||||
|
boolean hasChildren;
|
||||||
|
boolean allChildrenSelected;
|
||||||
|
|
||||||
|
public CheckedNode(boolean isSelected_, boolean hasChildren_, boolean allChildrenSelected_) {
|
||||||
|
isSelected = isSelected_;
|
||||||
|
hasChildren = hasChildren_;
|
||||||
|
allChildrenSelected = allChildrenSelected_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HashMap<TreePath, CheckedNode> nodesCheckingState;
|
||||||
|
HashSet<TreePath> checkedPaths = new HashSet<TreePath>();
|
||||||
|
|
||||||
|
// Defining a new event type for the checking mechanism and preparing event-handling mechanism
|
||||||
|
protected EventListenerList listenerList = new EventListenerList();
|
||||||
|
|
||||||
|
public class CheckChangeEvent extends EventObject {
|
||||||
|
private static final long serialVersionUID = -8100230309044193368L;
|
||||||
|
|
||||||
|
public CheckChangeEvent(Object source) {
|
||||||
|
super(source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface CheckChangeEventListener extends EventListener {
|
||||||
|
public void checkStateChanged(CheckChangeEvent event);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addCheckChangeEventListener(CheckChangeEventListener listener) {
|
||||||
|
listenerList.add(CheckChangeEventListener.class, listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeCheckChangeEventListener(CheckChangeEventListener listener) {
|
||||||
|
listenerList.remove(CheckChangeEventListener.class, listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearCheckChangeEventListeners() {
|
||||||
|
Object[] listeners = listenerList.getListenerList();
|
||||||
|
for (int i = listeners.length - 1; i >= 0; i--) {
|
||||||
|
if (listeners[i] == CheckChangeEventListener.class) {
|
||||||
|
listenerList.remove(CheckChangeEventListener.class, ((CheckChangeEventListener) listeners[i + 1]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fireCheckChangeEvent(CheckChangeEvent evt) {
|
||||||
|
Object[] listeners = listenerList.getListenerList();
|
||||||
|
for (int i = 0; i < listeners.length; i++) {
|
||||||
|
if (listeners[i] == CheckChangeEventListener.class) {
|
||||||
|
((CheckChangeEventListener) listeners[i + 1]).checkStateChanged(evt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Override
|
||||||
|
public void setModel(TreeModel newModel) {
|
||||||
|
super.setModel(newModel);
|
||||||
|
resetCheckingState();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void createModel(Object[] value) {
|
||||||
|
createTreeModel(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// New method that returns only the checked paths (totally ignores original "selection" mechanism)
|
||||||
|
public TreePath[] getCheckedPaths() {
|
||||||
|
return checkedPaths.toArray(new TreePath[checkedPaths.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true in case that the node is selected, has children but not all of them are selected
|
||||||
|
public boolean isSelectedPartially(TreePath path) {
|
||||||
|
CheckedNode cn = nodesCheckingState.get(path);
|
||||||
|
return cn.isSelected && cn.hasChildren && !cn.allChildrenSelected;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetCheckingState() {
|
||||||
|
nodesCheckingState = new HashMap<TreePath, CheckedNode>();
|
||||||
|
checkedPaths = new HashSet<TreePath>();
|
||||||
|
DefaultMutableTreeNode node = (DefaultMutableTreeNode) getModel().getRoot();
|
||||||
|
if (node == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
addSubtreeToCheckingStateTracking(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creating data structure of the current model for the checking mechanism
|
||||||
|
private void addSubtreeToCheckingStateTracking(DefaultMutableTreeNode node) {
|
||||||
|
TreeNode[] path = node.getPath();
|
||||||
|
TreePath tp = new TreePath(path);
|
||||||
|
CheckedNode cn = new CheckedNode(false, node.getChildCount() > 0, false);
|
||||||
|
nodesCheckingState.put(tp, cn);
|
||||||
|
for (int i = 0; i < node.getChildCount(); i++) {
|
||||||
|
addSubtreeToCheckingStateTracking((DefaultMutableTreeNode) tp.pathByAddingChild(node.getChildAt(i)).getLastPathComponent());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Overriding cell renderer by a class that ignores the original "selection" mechanism
|
||||||
|
// It decides how to show the nodes due to the checking-mechanism
|
||||||
|
private class CheckBoxCellRenderer extends JPanel implements TreeCellRenderer {
|
||||||
|
private static final long serialVersionUID = -7341833835878991719L;
|
||||||
|
JCheckBox checkBox;
|
||||||
|
|
||||||
|
public CheckBoxCellRenderer() {
|
||||||
|
super();
|
||||||
|
this.setLayout(new BorderLayout());
|
||||||
|
checkBox = new JCheckBox();
|
||||||
|
add(checkBox, BorderLayout.CENTER);
|
||||||
|
setOpaque(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Component getTreeCellRendererComponent(JTree tree, Object value,
|
||||||
|
boolean selected, boolean expanded, boolean leaf, int row,
|
||||||
|
boolean hasFocus) {
|
||||||
|
checkBox.setText(value.toString());
|
||||||
|
DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
|
||||||
|
TreePath tp = new TreePath(node.getPath());
|
||||||
|
CheckedNode cn = nodesCheckingState.get(tp);
|
||||||
|
if (cn == null) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
checkBox.setSelected(cn.isSelected);
|
||||||
|
checkBox.setOpaque(cn.isSelected && cn.hasChildren && !cn.allChildrenSelected);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public JCheckBoxTree() {
|
||||||
|
super();
|
||||||
|
// Disabling toggling by double-click
|
||||||
|
this.setToggleClickCount(0);
|
||||||
|
// Overriding cell renderer by new one defined above
|
||||||
|
CheckBoxCellRenderer cellRenderer = new CheckBoxCellRenderer();
|
||||||
|
this.setCellRenderer(cellRenderer);
|
||||||
|
|
||||||
|
// Overriding selection model by an empty one
|
||||||
|
DefaultTreeSelectionModel dtsm = new DefaultTreeSelectionModel() {
|
||||||
|
private static final long serialVersionUID = -8190634240451667286L;
|
||||||
|
|
||||||
|
// Totally disabling the selection mechanism
|
||||||
|
public void setSelectionPath(TreePath path) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addSelectionPath(TreePath path) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeSelectionPath(TreePath path) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSelectionPaths(TreePath[] pPaths) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// Calling checking mechanism on mouse click
|
||||||
|
this.addMouseListener(new MouseListener() {
|
||||||
|
public void mouseClicked(MouseEvent arg0) {
|
||||||
|
TreePath tp = selfPointer.getPathForLocation(arg0.getX(), arg0.getY());
|
||||||
|
if (tp == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
boolean checkMode = !nodesCheckingState.get(tp).isSelected;
|
||||||
|
checkSubTree(tp, checkMode);
|
||||||
|
updatePredecessorsWithCheckMode(tp, checkMode);
|
||||||
|
// Firing the check change event
|
||||||
|
fireCheckChangeEvent(new CheckChangeEvent(new Object()));
|
||||||
|
// Repainting tree after the data structures were updated
|
||||||
|
selfPointer.repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mouseEntered(MouseEvent arg0) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mouseExited(MouseEvent arg0) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mousePressed(MouseEvent arg0) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mouseReleased(MouseEvent arg0) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.setSelectionModel(dtsm);
|
||||||
|
}
|
||||||
|
|
||||||
|
// When a node is checked/unchecked, updating the states of the predecessors
|
||||||
|
protected void updatePredecessorsWithCheckMode(TreePath tp, boolean check) {
|
||||||
|
TreePath parentPath = tp.getParentPath();
|
||||||
|
// If it is the root, stop the recursive calls and return
|
||||||
|
if (parentPath == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
CheckedNode parentCheckedNode = nodesCheckingState.get(parentPath);
|
||||||
|
DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) parentPath.getLastPathComponent();
|
||||||
|
parentCheckedNode.allChildrenSelected = true;
|
||||||
|
parentCheckedNode.isSelected = false;
|
||||||
|
for (int i = 0; i < parentNode.getChildCount(); i++) {
|
||||||
|
TreePath childPath = parentPath.pathByAddingChild(parentNode.getChildAt(i));
|
||||||
|
CheckedNode childCheckedNode = nodesCheckingState.get(childPath);
|
||||||
|
// It is enough that even one subtree is not fully selected
|
||||||
|
// to determine that the parent is not fully selected
|
||||||
|
if (!childCheckedNode.allChildrenSelected) {
|
||||||
|
parentCheckedNode.allChildrenSelected = false;
|
||||||
|
}
|
||||||
|
// If at least one child is selected, selecting also the parent
|
||||||
|
if (childCheckedNode.isSelected) {
|
||||||
|
parentCheckedNode.isSelected = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (parentCheckedNode.isSelected) {
|
||||||
|
checkedPaths.add(parentPath);
|
||||||
|
} else {
|
||||||
|
checkedPaths.remove(parentPath);
|
||||||
|
}
|
||||||
|
// Go to upper predecessor
|
||||||
|
updatePredecessorsWithCheckMode(parentPath, check);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recursively checks/unchecks a subtree
|
||||||
|
protected void checkSubTree(TreePath tp, boolean check) {
|
||||||
|
CheckedNode cn = nodesCheckingState.get(tp);
|
||||||
|
cn.isSelected = check;
|
||||||
|
DefaultMutableTreeNode node = (DefaultMutableTreeNode) tp.getLastPathComponent();
|
||||||
|
for (int i = 0; i < node.getChildCount(); i++) {
|
||||||
|
checkSubTree(tp.pathByAddingChild(node.getChildAt(i)), check);
|
||||||
|
}
|
||||||
|
cn.allChildrenSelected = check;
|
||||||
|
if (check) {
|
||||||
|
checkedPaths.add(tp);
|
||||||
|
} else {
|
||||||
|
checkedPaths.remove(tp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void expandAllNodes() {
|
||||||
|
setTreeExpandedState(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void collapseAllNodes() {
|
||||||
|
setTreeExpandedState(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setTreeExpandedState(boolean expanded) {
|
||||||
|
DefaultMutableTreeNode node = (DefaultMutableTreeNode) getModel().getRoot();
|
||||||
|
setNodeExpandedState( node, expanded);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setNodeExpandedState(DefaultMutableTreeNode node, boolean expanded) {
|
||||||
|
ArrayList<TreeNode> list = Collections.list(node.children());
|
||||||
|
for (TreeNode treeNode : list) {
|
||||||
|
setNodeExpandedState((DefaultMutableTreeNode)treeNode, expanded);
|
||||||
|
}
|
||||||
|
if (!expanded && node.isRoot()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
TreePath path = new TreePath(node.getPath());
|
||||||
|
if (expanded) {
|
||||||
|
expandPath(path);
|
||||||
|
} else {
|
||||||
|
collapsePath(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package de.mc8051.arma3launcher.objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by gurkengewuerz.de on 25.03.2020.
|
||||||
|
*/
|
||||||
|
public interface AbstractMod {
|
||||||
|
|
||||||
|
public String getName();
|
||||||
|
}
|
@ -1,17 +1,40 @@
|
|||||||
package de.mc8051.arma3launcher.objects;
|
package de.mc8051.arma3launcher.objects;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by gurkengewuerz.de on 25.03.2020.
|
* Created by gurkengewuerz.de on 25.03.2020.
|
||||||
*/
|
*/
|
||||||
public class Mod {
|
public class Mod implements AbstractMod {
|
||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
|
private long size;
|
||||||
|
private ArrayList<ModFile> files;
|
||||||
|
|
||||||
public Mod(String name) {
|
public Mod(String name) {
|
||||||
|
this(name, -1, new ArrayList<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Mod(String name, long size, ArrayList<ModFile> files) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
|
this.size = size;
|
||||||
|
this.files = files;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<ModFile> getFiles() {
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getSize() {
|
||||||
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Mod clone() {
|
||||||
|
return new Mod(name, size, new ArrayList<>(files));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
82
src/main/java/de/mc8051/arma3launcher/objects/ModFile.java
Normal file
82
src/main/java/de/mc8051/arma3launcher/objects/ModFile.java
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
package de.mc8051.arma3launcher.objects;
|
||||||
|
|
||||||
|
import org.apache.commons.io.FilenameUtils;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by gurkengewuerz.de on 25.03.2020.
|
||||||
|
*/
|
||||||
|
public class ModFile implements AbstractMod {
|
||||||
|
|
||||||
|
private File f;
|
||||||
|
private long size;
|
||||||
|
private String folder;
|
||||||
|
private String filename;
|
||||||
|
private String extension;
|
||||||
|
private String modfileString;
|
||||||
|
|
||||||
|
public ModFile(File f, String modfile, long size) {
|
||||||
|
// File: Abosolut Path
|
||||||
|
// modfile: addons/config/something.pbo
|
||||||
|
// size: size as in metafile on server
|
||||||
|
this.f = f;
|
||||||
|
this.size = size;
|
||||||
|
this.folder = FilenameUtils.getPath(modfile);
|
||||||
|
this.filename = FilenameUtils.getBaseName(modfile);
|
||||||
|
this.extension = FilenameUtils.getExtension(modfile);
|
||||||
|
this.modfileString = modfile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getSize() {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getReletaivePath() {
|
||||||
|
return folder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFilename() {
|
||||||
|
return filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getExtension() {
|
||||||
|
return extension;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<String> getPath() {
|
||||||
|
ArrayList<String> list = new ArrayList<>();
|
||||||
|
File relativePath = new File("./"+ modfileString);
|
||||||
|
do {
|
||||||
|
list.add(relativePath.getName());
|
||||||
|
relativePath = relativePath.getParentFile();
|
||||||
|
} while (relativePath.getParentFile() != null);
|
||||||
|
list.remove(0);
|
||||||
|
Collections.reverse(list);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getLocalSize() {
|
||||||
|
if(!f.exists() || !f.isFile()) return -1;
|
||||||
|
return f.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean exists() {
|
||||||
|
if(!f.exists() || !f.isFile()) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return filename + (extension.equals("") ? "" : "." + extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getModfileString() {
|
||||||
|
return modfileString;
|
||||||
|
}
|
||||||
|
|
||||||
|
public File getLocaleFile() {
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
}
|
@ -56,6 +56,10 @@ public class Modset {
|
|||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void play() {
|
||||||
|
// TODO: Implement play with this Modset
|
||||||
|
}
|
||||||
|
|
||||||
public static enum Type {
|
public static enum Type {
|
||||||
SERVER,
|
SERVER,
|
||||||
CLIENT
|
CLIENT
|
||||||
|
@ -0,0 +1,10 @@
|
|||||||
|
package de.mc8051.arma3launcher.repo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by gurkengewuerz.de on 25.03.2020.
|
||||||
|
*/
|
||||||
|
public enum DownloadStatus {
|
||||||
|
RUNNING,
|
||||||
|
FINNISHED,
|
||||||
|
ERROR;
|
||||||
|
}
|
203
src/main/java/de/mc8051/arma3launcher/repo/FileChecker.java
Normal file
203
src/main/java/de/mc8051/arma3launcher/repo/FileChecker.java
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
package de.mc8051.arma3launcher.repo;
|
||||||
|
|
||||||
|
import de.mc8051.arma3launcher.ArmA3Launcher;
|
||||||
|
import de.mc8051.arma3launcher.interfaces.Observable;
|
||||||
|
import de.mc8051.arma3launcher.interfaces.Observer;
|
||||||
|
import de.mc8051.arma3launcher.objects.AbstractMod;
|
||||||
|
import de.mc8051.arma3launcher.objects.Mod;
|
||||||
|
import de.mc8051.arma3launcher.objects.ModFile;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.Array;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by gurkengewuerz.de on 26.03.2020.
|
||||||
|
*/
|
||||||
|
public class FileChecker implements Observable {
|
||||||
|
|
||||||
|
private List<Observer> observerList = new ArrayList<>();
|
||||||
|
private JProgressBar pb;
|
||||||
|
private boolean stop = false;
|
||||||
|
|
||||||
|
ArrayList<Path> deleted = new ArrayList<>();
|
||||||
|
HashMap<String, ArrayList<ModFile>> changed = new HashMap<>();
|
||||||
|
int changedCount = 0;
|
||||||
|
HashMap<String, ArrayList<ModFile>> added = new HashMap<>();
|
||||||
|
int addedCount = 0;
|
||||||
|
|
||||||
|
long size = 0;
|
||||||
|
|
||||||
|
public FileChecker(JProgressBar pb) {
|
||||||
|
this.pb = pb;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void check() {
|
||||||
|
deleted.clear();
|
||||||
|
changed.clear();
|
||||||
|
changedCount = 0;
|
||||||
|
added.clear();
|
||||||
|
addedCount = 0;
|
||||||
|
size = 0;
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
pb.setMaximum(RepositoryManger.MOD_LIST_SIZE);
|
||||||
|
pb.setValue(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
for (AbstractMod abstractMod : RepositoryManger.MOD_LIST) {
|
||||||
|
if(stop) {
|
||||||
|
stop = false;
|
||||||
|
notifyObservers("fileCheckerStopped");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(abstractMod instanceof Mod) {
|
||||||
|
Mod m = (Mod) abstractMod;
|
||||||
|
|
||||||
|
for (ModFile mf : m.getFiles()) {
|
||||||
|
checkFile(mf.getName(), mf);
|
||||||
|
i++;
|
||||||
|
int finalI = i;
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
pb.setValue(finalI);
|
||||||
|
});
|
||||||
|
|
||||||
|
if(stop) {
|
||||||
|
stop = false;
|
||||||
|
notifyObservers("fileCheckerStopped");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (abstractMod instanceof ModFile) {
|
||||||
|
ModFile mf = (ModFile) abstractMod;
|
||||||
|
checkFile(mf.getName(), mf);
|
||||||
|
i++;
|
||||||
|
int finalI1 = i;
|
||||||
|
SwingUtilities.invokeLater(() -> {
|
||||||
|
pb.setValue(finalI1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
checkDeleted();
|
||||||
|
notifyObservers("fileChecker");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stop() {
|
||||||
|
stop = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkFile(String mod, ModFile mf) {
|
||||||
|
// TODO: Add mf to Array if Array already exists
|
||||||
|
if(!mf.exists()) {
|
||||||
|
added.put(mod, mf);
|
||||||
|
addedCount++;
|
||||||
|
size += mf.getSize();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mf.getLocalSize() != mf.getSize()) {
|
||||||
|
changed.put(mod, mf);
|
||||||
|
changedCount++;
|
||||||
|
size += mf.getSize();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkDeleted() {
|
||||||
|
String modPath = ArmA3Launcher.user_config.get("client", "modPath");
|
||||||
|
if(modPath == null) modPath = "";
|
||||||
|
|
||||||
|
try {
|
||||||
|
List<Path> filePathList = Files.find(Paths.get(modPath),
|
||||||
|
Integer.MAX_VALUE,
|
||||||
|
(filePath, fileAttr) -> fileAttr.isRegularFile())
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
|
||||||
|
for (Path localPath : filePathList) {
|
||||||
|
ModFile deleteable = null;
|
||||||
|
|
||||||
|
outerloop:
|
||||||
|
for (AbstractMod abstractMod : RepositoryManger.MOD_LIST) {
|
||||||
|
if(abstractMod instanceof Mod) {
|
||||||
|
Mod m = (Mod) abstractMod;
|
||||||
|
|
||||||
|
for (ModFile mf : m.getFiles()) {
|
||||||
|
if (mf.getLocaleFile().getPath().equals(localPath.toString())) {
|
||||||
|
deleteable = mf;
|
||||||
|
break outerloop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (abstractMod instanceof ModFile) {
|
||||||
|
ModFile mf = (ModFile) abstractMod;
|
||||||
|
if (mf.getLocaleFile().getPath().equals(localPath.toString())) {
|
||||||
|
deleteable = mf;
|
||||||
|
break outerloop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deleteable == null) {
|
||||||
|
deleted.add(localPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<Path> getDeleted() {
|
||||||
|
return deleted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HashMap<String, ArrayList<ModFile>> getChanged() {
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HashMap<String, ArrayList<ModFile>> getAdded() {
|
||||||
|
return added;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDeletedCount() {
|
||||||
|
return deleted.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getChangedCount() {
|
||||||
|
return changedCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAddedCount() {
|
||||||
|
return addedCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getSize() {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addObserver(Observer observer) {
|
||||||
|
observerList.add(observer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeObserver(Observer observer) {
|
||||||
|
observerList.remove(observer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void notifyObservers(String obj) {
|
||||||
|
for (Observer obs : observerList) obs.update(obj);
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,9 @@ package de.mc8051.arma3launcher.repo;
|
|||||||
import de.mc8051.arma3launcher.ArmA3Launcher;
|
import de.mc8051.arma3launcher.ArmA3Launcher;
|
||||||
import de.mc8051.arma3launcher.interfaces.Observable;
|
import de.mc8051.arma3launcher.interfaces.Observable;
|
||||||
import de.mc8051.arma3launcher.interfaces.Observer;
|
import de.mc8051.arma3launcher.interfaces.Observer;
|
||||||
|
import de.mc8051.arma3launcher.objects.AbstractMod;
|
||||||
|
import de.mc8051.arma3launcher.objects.Mod;
|
||||||
|
import de.mc8051.arma3launcher.objects.ModFile;
|
||||||
import de.mc8051.arma3launcher.objects.Modset;
|
import de.mc8051.arma3launcher.objects.Modset;
|
||||||
import de.mc8051.arma3launcher.objects.Server;
|
import de.mc8051.arma3launcher.objects.Server;
|
||||||
import de.mc8051.arma3launcher.utils.Callback;
|
import de.mc8051.arma3launcher.utils.Callback;
|
||||||
@ -12,8 +15,11 @@ import okhttp3.Response;
|
|||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
@ -24,19 +30,49 @@ import java.util.logging.Logger;
|
|||||||
public class RepositoryManger implements Observable {
|
public class RepositoryManger implements Observable {
|
||||||
|
|
||||||
private static RepositoryManger instance;
|
private static RepositoryManger instance;
|
||||||
|
|
||||||
|
public static ArrayList<AbstractMod> MOD_LIST = new ArrayList<>();
|
||||||
|
public static int MOD_LIST_SIZE = 0;
|
||||||
|
private static HashMap<Type, DownloadStatus> statusMap = new HashMap<>();
|
||||||
|
|
||||||
private List<Observer> observerList = new ArrayList<>();
|
private List<Observer> observerList = new ArrayList<>();
|
||||||
private OkHttpClient client = new OkHttpClient();
|
private OkHttpClient client = new OkHttpClient();
|
||||||
|
|
||||||
private RepositoryManger() {
|
private RepositoryManger() {
|
||||||
|
statusMap.put(Type.METADATA, DownloadStatus.FINNISHED);
|
||||||
|
statusMap.put(Type.MODSET, DownloadStatus.FINNISHED);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getAsync(String url, Callback.HttpCallback callback) {
|
||||||
|
new Thread(() -> {
|
||||||
|
try {
|
||||||
|
Request request = new Request.Builder()
|
||||||
|
.url(url)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Response r = client.newCall(request).execute();
|
||||||
|
if (!r.isSuccessful()) {
|
||||||
|
Logger.getLogger(getClass().getName()).log(Level.SEVERE, "Cant open " + r.request().url().toString() + " code " + r.code());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
callback.response(r);
|
||||||
|
} catch (IOException e) {
|
||||||
|
Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, e);
|
||||||
|
callback.response(null);
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void refreshMeta() {
|
public void refreshMeta() {
|
||||||
downloadMeta(new Callback.HttpCallback() {
|
statusMap.replace(Type.METADATA, DownloadStatus.RUNNING);
|
||||||
|
RepositoryManger.getInstance().notifyObservers(Type.METADATA.toString());
|
||||||
|
getAsync(ArmA3Launcher.config.getString("sync.url") + "/.sync/server.json", new Callback.HttpCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void response(Response r) {
|
public void response(Response r) {
|
||||||
if (!r.isSuccessful()) {
|
if (!r.isSuccessful()) {
|
||||||
Logger.getLogger(getClass().getName()).log(Level.SEVERE, "Cant open " + r.request().url().toString() + " code " + r.code());
|
statusMap.replace(Type.METADATA, DownloadStatus.ERROR);
|
||||||
RepositoryManger.getInstance().notifyObservers("refreshMetaFailed");
|
RepositoryManger.getInstance().notifyObservers(Type.METADATA.toString());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,6 +80,7 @@ public class RepositoryManger implements Observable {
|
|||||||
JSONObject jsonObject = new JSONObject(r.body().string());
|
JSONObject jsonObject = new JSONObject(r.body().string());
|
||||||
|
|
||||||
if (jsonObject.has("modsets")) {
|
if (jsonObject.has("modsets")) {
|
||||||
|
Modset.MODSET_LIST.clear();
|
||||||
JSONArray modsets = jsonObject.getJSONArray("modsets");
|
JSONArray modsets = jsonObject.getJSONArray("modsets");
|
||||||
if (modsets.length() > 0) {
|
if (modsets.length() > 0) {
|
||||||
for (int i = 0; i < modsets.length(); i++) {
|
for (int i = 0; i < modsets.length(); i++) {
|
||||||
@ -55,6 +92,7 @@ public class RepositoryManger implements Observable {
|
|||||||
|
|
||||||
// Init servers after modsets because server search preset string in modsets
|
// Init servers after modsets because server search preset string in modsets
|
||||||
if (jsonObject.has("servers")) {
|
if (jsonObject.has("servers")) {
|
||||||
|
Server.SERVER_LIST.clear();
|
||||||
JSONArray servers = jsonObject.getJSONArray("servers");
|
JSONArray servers = jsonObject.getJSONArray("servers");
|
||||||
if (servers.length() > 0) {
|
if (servers.length() > 0) {
|
||||||
for (int i = 0; i < servers.length(); i++) {
|
for (int i = 0; i < servers.length(); i++) {
|
||||||
@ -64,7 +102,8 @@ public class RepositoryManger implements Observable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RepositoryManger.getInstance().notifyObservers("refreshMeta");
|
statusMap.replace(Type.METADATA, DownloadStatus.FINNISHED);
|
||||||
|
RepositoryManger.getInstance().notifyObservers(Type.METADATA.toString());
|
||||||
} catch (IOException | NullPointerException e) {
|
} catch (IOException | NullPointerException e) {
|
||||||
Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, e);
|
Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, e);
|
||||||
}
|
}
|
||||||
@ -72,19 +111,68 @@ public class RepositoryManger implements Observable {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void downloadMeta(Callback.HttpCallback callback) {
|
public void refreshModset() {
|
||||||
new Thread(() -> {
|
statusMap.replace(Type.MODSET, DownloadStatus.RUNNING);
|
||||||
try {
|
RepositoryManger.getInstance().notifyObservers(Type.MODSET.toString());
|
||||||
Request request = new Request.Builder()
|
getAsync(ArmA3Launcher.config.getString("sync.url") + "/.sync/modset.json", new Callback.HttpCallback() {
|
||||||
.url(ArmA3Launcher.config.getString("sync.url") + "/.sync/server.json")
|
@Override
|
||||||
.build();
|
public void response(Response r) {
|
||||||
|
if (!r.isSuccessful()) {
|
||||||
|
statusMap.replace(Type.MODSET, DownloadStatus.ERROR);
|
||||||
|
RepositoryManger.getInstance().notifyObservers(Type.MODSET.toString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
callback.response(client.newCall(request).execute());
|
try {
|
||||||
} catch (IOException e) {
|
RepositoryManger.MOD_LIST.clear();
|
||||||
Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, e);
|
RepositoryManger.MOD_LIST_SIZE = 0;
|
||||||
callback.response(null);
|
JSONObject jsonObject = new JSONObject(r.body().string());
|
||||||
|
|
||||||
|
String modPath = ArmA3Launcher.user_config.get("client", "modPath");
|
||||||
|
if(modPath == null) modPath = "";
|
||||||
|
|
||||||
|
String finalModPath = modPath;
|
||||||
|
jsonObject.keySet().forEach(modname ->
|
||||||
|
{
|
||||||
|
Object keyvalue = jsonObject.get(modname);
|
||||||
|
|
||||||
|
if (!(keyvalue instanceof JSONObject)) return;
|
||||||
|
|
||||||
|
JSONObject jsonMod = (JSONObject)keyvalue;
|
||||||
|
if(!jsonMod.has("size")) return;
|
||||||
|
|
||||||
|
long modsize = jsonMod.getLong("size");
|
||||||
|
|
||||||
|
if(jsonMod.has("content")) {
|
||||||
|
// Mod Directory
|
||||||
|
JSONObject content = jsonMod.getJSONObject("content");
|
||||||
|
|
||||||
|
ArrayList<ModFile> modFiles = new ArrayList<>();
|
||||||
|
Iterator<String> keys = content.keys();
|
||||||
|
while (keys.hasNext()) {
|
||||||
|
String modfile = keys.next();
|
||||||
|
long modfilesize = content.getLong(modfile);
|
||||||
|
|
||||||
|
modFiles.add(new ModFile(new File(finalModPath + File.separator + modname + File.separator + modfile), modfile, modfilesize));
|
||||||
|
RepositoryManger.MOD_LIST_SIZE++;
|
||||||
|
}
|
||||||
|
|
||||||
|
MOD_LIST.add(new Mod(modname, modsize, modFiles));
|
||||||
|
} else {
|
||||||
|
// Single File
|
||||||
|
MOD_LIST.add(new ModFile(new File(finalModPath + File.separator + modname), modname, modsize));
|
||||||
|
RepositoryManger.MOD_LIST_SIZE++;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
statusMap.replace(Type.MODSET, DownloadStatus.FINNISHED);
|
||||||
|
RepositoryManger.getInstance().notifyObservers(Type.MODSET.toString());
|
||||||
|
} catch (IOException | NullPointerException e) {
|
||||||
|
Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}).start();
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static RepositoryManger getInstance() {
|
public static RepositoryManger getInstance() {
|
||||||
@ -92,6 +180,10 @@ public class RepositoryManger implements Observable {
|
|||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DownloadStatus getStatus(Type type) {
|
||||||
|
return statusMap.get(type);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addObserver(Observer observer) {
|
public void addObserver(Observer observer) {
|
||||||
observerList.add(observer);
|
observerList.add(observer);
|
||||||
@ -103,7 +195,24 @@ public class RepositoryManger implements Observable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void notifyObservers(Object obj) {
|
public void notifyObservers(String obj) {
|
||||||
for (Observer obs : observerList) obs.update(obj);
|
for (Observer obs : observerList) obs.update(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum Type {
|
||||||
|
|
||||||
|
METADATA("metadata"),
|
||||||
|
MODSET("modset");
|
||||||
|
|
||||||
|
private String modset;
|
||||||
|
|
||||||
|
Type(String modset) {
|
||||||
|
this.modset = modset;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return modset;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
8
src/main/java/de/mc8051/arma3launcher/repo/Syncer.java
Normal file
8
src/main/java/de/mc8051/arma3launcher/repo/Syncer.java
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package de.mc8051.arma3launcher.repo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by gurkengewuerz.de on 25.03.2020.
|
||||||
|
*/
|
||||||
|
public class Syncer {
|
||||||
|
// FilenameUtils.directoryContains
|
||||||
|
}
|
@ -2,10 +2,12 @@ package de.mc8051.arma3launcher.steam;
|
|||||||
|
|
||||||
import de.mc8051.arma3launcher.LauncherGUI;
|
import de.mc8051.arma3launcher.LauncherGUI;
|
||||||
import de.mc8051.arma3launcher.SteamUtils;
|
import de.mc8051.arma3launcher.SteamUtils;
|
||||||
|
import de.mc8051.arma3launcher.interfaces.Observer;
|
||||||
import de.ralleytn.simple.registry.Key;
|
import de.ralleytn.simple.registry.Key;
|
||||||
import de.ralleytn.simple.registry.Registry;
|
import de.ralleytn.simple.registry.Registry;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
@ -15,24 +17,22 @@ import java.util.logging.Logger;
|
|||||||
*/
|
*/
|
||||||
public class SteamTimer extends TimerTask {
|
public class SteamTimer extends TimerTask {
|
||||||
|
|
||||||
|
private static ArrayList<Observer> observers = new ArrayList<>();
|
||||||
public static boolean steam_running = false;
|
public static boolean steam_running = false;
|
||||||
public static boolean arma_running = false;
|
public static boolean arma_running = false;
|
||||||
|
|
||||||
private LauncherGUI gui;
|
|
||||||
|
|
||||||
public SteamTimer(LauncherGUI gui) {
|
|
||||||
this.gui = gui;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
String OS = System.getProperty("os.name").toUpperCase();
|
String OS = System.getProperty("os.name").toUpperCase();
|
||||||
if (!OS.contains("WIN")) return;
|
if (!OS.contains("WIN")) return;
|
||||||
|
|
||||||
|
boolean old_steamrunning = steam_running;
|
||||||
|
boolean old_arma_running = arma_running;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if(!SteamUtils.findProcess("steam.exe")) {
|
if(!SteamUtils.findProcess("steam.exe")) {
|
||||||
steam_running = false;
|
steam_running = false;
|
||||||
gui.updateLabels(steam_running, arma_running);
|
if(old_steamrunning != steam_running) notifyObservers("steamtimer");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,19 +42,28 @@ public class SteamTimer extends TimerTask {
|
|||||||
|
|
||||||
if(activeSteamUser.equals("0x0")) {
|
if(activeSteamUser.equals("0x0")) {
|
||||||
steam_running = false;
|
steam_running = false;
|
||||||
gui.updateLabels(steam_running, arma_running);
|
if(old_steamrunning != steam_running) notifyObservers("steamtimer");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
steam_running = true;
|
steam_running = true;
|
||||||
|
|
||||||
arma_running = SteamUtils.findProcess("arma3.exe") || SteamUtils.findProcess("arma3_x64.exe") || SteamUtils.findProcess("arma3launcher.exe");
|
arma_running = SteamUtils.findProcess("arma3.exe") || SteamUtils.findProcess("arma3_x64.exe") || SteamUtils.findProcess("arma3launcher.exe");
|
||||||
|
|
||||||
|
if(old_steamrunning != steam_running || old_arma_running != arma_running) notifyObservers("steamtimer");
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
steam_running = false;
|
steam_running = false;
|
||||||
arma_running = false;
|
arma_running = false;
|
||||||
|
notifyObservers("steamtimer");
|
||||||
Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, e);
|
Logger.getLogger(getClass().getName()).log(Level.SEVERE, null, e);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
gui.updateLabels(steam_running, arma_running);
|
public static void addObserver(Observer observer) {
|
||||||
|
observers.add(observer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void notifyObservers(String obj) {
|
||||||
|
for(Observer o : observers) o.update(obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
arma_running=ArmA läuft noch. Bitte beende ArmA.
|
||||||
abort=Abbrechen
|
abort=Abbrechen
|
||||||
arm33_parameter=ArmA 3 Startparameter
|
arm33_parameter=ArmA 3 Startparameter
|
||||||
arma3_installpath=ArmA 3 Installationspfad
|
arma3_installpath=ArmA 3 Installationspfad
|
||||||
@ -65,7 +66,7 @@ showscripterrors_desc=Fehler in Scripten werden in einem Hinweistext signalisier
|
|||||||
signed_in=eingeloggt
|
signed_in=eingeloggt
|
||||||
speed=Geschwindigkeit
|
speed=Geschwindigkeit
|
||||||
speed_up_game=Spielstart beschleunigen
|
speed_up_game=Spielstart beschleunigen
|
||||||
spikintro_desc=Die Intro-Sequenz wird übersprungen.
|
skipintro_desc=Die Intro-Sequenz wird übersprungen.
|
||||||
total_file_size=Gesamtgröße
|
total_file_size=Gesamtgröße
|
||||||
update=Update
|
update=Update
|
||||||
use64bitclient_desc=Startet Arma3 mit der für 64-Bit Betriebssysteme optimierten .exe-Datei (kann die Performance von Arma 3 verbessern und Probleme beheben (bspw. 3-FPS-Bug).
|
use64bitclient_desc=Startet Arma3 mit der für 64-Bit Betriebssysteme optimierten .exe-Datei (kann die Performance von Arma 3 verbessern und Probleme beheben (bspw. 3-FPS-Bug).
|
||||||
@ -79,4 +80,14 @@ du sie deaktivieren und ohne diese Option erneut syncen.\
|
|||||||
\
|
\
|
||||||
Ebenfalls könnte es zu kurzen Performance einbußen kommen.
|
Ebenfalls könnte es zu kurzen Performance einbußen kommen.
|
||||||
window_desc=Ist diese Option aktiv, wird Arma 3 im Fenstermodus gestartet.
|
window_desc=Ist diese Option aktiv, wird Arma 3 im Fenstermodus gestartet.
|
||||||
world_desc=Hier kann eine Karte eingetragen werden, die geladen und in den Menüs als Hintergrund angezeigt werden soll (z.B. „altis“ oder „stratis“ – ohne Anführungszeichen!). Ist das Feld leer, wird keine Karte während des Startens geladen und der Start von Arma 3 ist entsprechend schneller.
|
world_desc=Hier kann eine Karte eingetragen werden, die geladen und in den Menüs als Hintergrund angezeigt werden soll (z.B. „altis“ oder „stratis“ – ohne Anführungszeichen!). Ist das Feld leer, wird keine Karte während des Startens geladen und der Start von Arma 3 ist entsprechend schneller.
|
||||||
|
path_not_set=ArmA oder Mod Verzeichnis nicht gesetzt
|
||||||
|
steam_not_running=Steam läuft nicht. Bitte starte Steam.
|
||||||
|
update_repository=Repository aktualisieren
|
||||||
|
collapse_all=Alles einklappen
|
||||||
|
same_mod_arma_dir_msg=Das ArmA sowie Mod Verzeichnis dürfen nicht identisch sein.
|
||||||
|
same_mod_arma_dir=Gleiches Verzeichnis
|
||||||
|
check_local_addons=Lokale Dateien überprüfen
|
||||||
|
changed_files=Veränderte Datien
|
||||||
|
added_files=Hinzugefügte Datien
|
||||||
|
deleted_files=Gelöschte Dateien
|
@ -1,6 +1,7 @@
|
|||||||
abort=Abort
|
abort=Abort
|
||||||
arm33_parameter=ArmA 3 Start parameters
|
arm33_parameter=ArmA 3 Start parameters
|
||||||
arma3_installpath=ArmA 3 Installation path
|
arma3_installpath=ArmA 3 Installation path
|
||||||
|
arma_running=ArmA is still running. Please exit ArmA.
|
||||||
backend_url=Backend URL
|
backend_url=Backend URL
|
||||||
behaviour_aafter_start=Behaviour after start
|
behaviour_aafter_start=Behaviour after start
|
||||||
beta_desc=Data from subdirectories can be started as well.
|
beta_desc=Data from subdirectories can be started as well.
|
||||||
@ -64,7 +65,7 @@ showscripterrors_desc=Errors in scripts are signaled in a message text.
|
|||||||
signed_in=signed in
|
signed_in=signed in
|
||||||
speed=Speed
|
speed=Speed
|
||||||
speed_up_game=Speed up game start
|
speed_up_game=Speed up game start
|
||||||
spikintro_desc=The intro sequence is skipped.
|
skipintro_desc=The intro sequence is skipped.
|
||||||
total_file_size=Total file size
|
total_file_size=Total file size
|
||||||
update=Update
|
update=Update
|
||||||
use64bitclient_desc=Starts Arma3 with the .exe file optimized for 64-bit operating systems (can improve the performance of Arma 3 and fix problems (e.g. 3-FPS bug)
|
use64bitclient_desc=Starts Arma3 with the .exe file optimized for 64-bit operating systems (can improve the performance of Arma 3 and fix problems (e.g. 3-FPS bug)
|
||||||
@ -78,4 +79,10 @@ you deactivate it and sync again without this option.\
|
|||||||
\
|
\
|
||||||
This could also lead to short performance losses.
|
This could also lead to short performance losses.
|
||||||
window_desc=If this option is active, Arma 3 is started in windowed mode.
|
window_desc=If this option is active, Arma 3 is started in windowed mode.
|
||||||
world_desc=Here you can enter a card to be loaded and displayed as background in the menus (e.g. "altis" or "stratis" - without quotation marks!). If the field is empty, no map will be loaded during startup and the start of Arma 3 will be faster.
|
world_desc=Here you can enter a card to be loaded and displayed as background in the menus (e.g. "altis" or "stratis" - without quotation marks!). If the field is empty, no map will be loaded during startup and the start of Arma 3 will be faster.
|
||||||
|
path_not_set=ArmA or Mod directory not set
|
||||||
|
steam_not_running=Steam not running. Please start Steam.
|
||||||
|
repository_content=Repository Content
|
||||||
|
collapse_all=Collapse All
|
||||||
|
same_mod_arma_dir_msg=The ArmA and Mod directory must not be identical.
|
||||||
|
same_mod_arma_dir=Same directory
|
Loading…
Reference in New Issue
Block a user