4
4
import com .falsepattern .lib .StableAPI ;
5
5
import com .falsepattern .lib .dependencies .DependencyLoader ;
6
6
import com .falsepattern .lib .dependencies .SemanticVersion ;
7
- import com .falsepattern .lib .internal .FalsePatternLib ;
8
7
import com .falsepattern .lib .internal .Internet ;
9
8
import com .falsepattern .lib .internal .LibraryConfig ;
10
9
import com .falsepattern .lib .internal .Tags ;
11
10
import com .falsepattern .lib .text .FormattedText ;
12
- import com .falsepattern .lib .util .AsyncUtil ;
13
11
import cpw .mods .fml .common .Loader ;
14
12
import lombok .val ;
15
13
import net .minecraft .client .resources .I18n ;
16
14
import net .minecraft .event .ClickEvent ;
17
15
import net .minecraft .util .IChatComponent ;
18
16
19
- import java .io .ByteArrayOutputStream ;
20
- import java .io .IOException ;
21
17
import java .net .MalformedURLException ;
22
18
import java .net .URL ;
23
19
import java .util .ArrayList ;
24
20
import java .util .Collections ;
25
21
import java .util .List ;
26
- import java .util .concurrent .Future ;
27
- import java .util .concurrent .atomic . AtomicInteger ;
28
- import java .util .concurrent .atomic .AtomicReference ;
22
+ import java .util .concurrent .CompletableFuture ;
23
+ import java .util .concurrent .CompletionException ;
24
+ import java .util .concurrent .atomic .AtomicBoolean ;
29
25
30
26
@ StableAPI (since = "0.8.0" )
31
27
public class UpdateChecker {
32
- private static final AtomicInteger jsonLibraryLoaded = new AtomicInteger (0 );
33
- /**
34
- * Same this as {@link #fetchUpdates(String)}, but defers the check to a different thread. Useful for asynchronous
35
- * update checks, if you don't want to block loading.
36
- * @param url The URL to check
37
- * @return A future that will contain the update info about mods that were both available on the URL and installed
38
- */
39
- public static Future <List <ModUpdateInfo >> fetchUpdatesAsync (String url ) {
40
- return AsyncUtil .asyncWorker .submit (() -> fetchUpdates (url ));
41
- }
28
+ private static final AtomicBoolean jsonLibraryLoaded = new AtomicBoolean (false );
29
+
42
30
43
31
/**
44
32
* Checks for updates. The URL should be a JSON file that contains a list of mods, each with a mod ID, one or more
@@ -62,21 +50,20 @@ public static Future<List<ModUpdateInfo>> fetchUpdatesAsync(String url) {
62
50
* @param url The URL to check
63
51
* @return A list of mods that were both available on the URL and installed
64
52
*/
65
- public static List <ModUpdateInfo > fetchUpdates (String url ) {
66
- if (!LibraryConfig .ENABLE_UPDATE_CHECKER ) {
67
- return null ;
68
- }
69
- URL URL ;
70
- try {
71
- URL = new URL (url );
72
- } catch (MalformedURLException e ) {
73
- FalsePatternLib .getLog ().error ("Invalid URL: {}" , url , e );
74
- return null ;
75
- }
76
- switch (jsonLibraryLoaded .get ()) {
77
- case 0 :
78
- DependencyLoader .addMavenRepo ("https://maven.falsepattern.com/" );
53
+ public static CompletableFuture <List <ModUpdateInfo >> fetchUpdatesAsync (String url ) {
54
+ return CompletableFuture .supplyAsync (() -> {
55
+ if (!LibraryConfig .ENABLE_UPDATE_CHECKER ) {
56
+ throw new CompletionException (new UpdateCheckException ("Update checker is disabled in config!" ));
57
+ }
58
+ URL URL ;
59
+ try {
60
+ URL = new URL (url );
61
+ } catch (MalformedURLException e ) {
62
+ throw new CompletionException (new UpdateCheckException ("Invalid URL: " + url , e ));
63
+ }
64
+ if (!jsonLibraryLoaded .get ()) {
79
65
try {
66
+ DependencyLoader .addMavenRepo ("https://maven.falsepattern.com/" );
80
67
DependencyLoader .builder ()
81
68
.loadingModId (Tags .MODID )
82
69
.groupId ("com.falsepattern" )
@@ -86,61 +73,71 @@ public static List<ModUpdateInfo> fetchUpdates(String url) {
86
73
.preferredVersion (new SemanticVersion (0 , 4 , 1 ))
87
74
.build ();
88
75
} catch (Exception e ) {
89
- FalsePatternLib .getLog ().error ("Failed to load json library for update checker!" , e );
90
- jsonLibraryLoaded .set (-1 );
91
- return null ;
76
+ throw new CompletionException (new UpdateCheckException ("Failed to load json library for update checker!" , e ));
92
77
}
93
- jsonLibraryLoaded .set (1 );
94
- break ;
95
- case -1 :
96
- return null ;
97
- }
98
- AtomicReference <String > loadedData = new AtomicReference <>(null );
99
- Internet .connect (URL , (ex ) -> FalsePatternLib .getLog ().warn ("Failed to check for updates from URL {}" , url , ex ), (input ) -> {
100
- val data = new ByteArrayOutputStream ();
78
+ jsonLibraryLoaded .set (true );
79
+ }
80
+ val result = new ArrayList <ModUpdateInfo >();
81
+ JsonNode parsed ;
101
82
try {
102
- Internet .transferAndClose ( input , data );
103
- } catch (IOException e ) {
104
- throw new RuntimeException ( e );
83
+ parsed = JsonNode . parse ( Internet .download ( URL ). thenApply ( String :: new ). join () );
84
+ } catch (CompletionException e ) {
85
+ throw new CompletionException ( new UpdateCheckException ( "Failed to download update checker JSON file!" , e . getCause () == null ? e : e . getCause ()) );
105
86
}
106
- loadedData .set (data .toString ());
107
- });
108
- if (loadedData .get () == null ) return null ;
109
- val result = new ArrayList <ModUpdateInfo >();
110
- val parsed = JsonNode .parse (loadedData .get ());
111
- List <JsonNode > modList ;
112
- if (parsed .isList ()) {
113
- modList = parsed .getJavaList ();
114
- } else {
115
- modList = Collections .singletonList (parsed );
116
- }
117
- val installedMods = Loader .instance ().getIndexedModList ();
118
- for (val node : modList ) {
119
- if (!node .isObject ()) continue ;
120
- if (!node .containsKey ("modid" )) continue ;
121
- if (!node .containsKey ("latestVersion" )) continue ;
122
- val modid = node .getString ("modid" );
123
- if (!installedMods .containsKey (modid )) continue ;
124
- val mod = installedMods .get (modid );
125
- val latestVersionsNode = node .get ("latestVersion" );
126
- List <String > latestVersions ;
127
- if (latestVersionsNode .isString ()) {
128
- latestVersions = Collections .singletonList (latestVersionsNode .stringValue ());
129
- } else if (latestVersionsNode .isList ()) {
130
- latestVersions = new ArrayList <>();
131
- for (val version : latestVersionsNode .getJavaList ()) {
132
- if (!version .isString ()) continue ;
133
- latestVersions .add (version .stringValue ());
134
- }
87
+ List <JsonNode > modList ;
88
+ if (parsed .isList ()) {
89
+ modList = parsed .getJavaList ();
135
90
} else {
136
- continue ;
91
+ modList = Collections .singletonList (parsed );
92
+ }
93
+ val installedMods = Loader .instance ().getIndexedModList ();
94
+ for (val node : modList ) {
95
+ if (!node .isObject ()) continue ;
96
+ if (!node .containsKey ("modid" )) continue ;
97
+ if (!node .containsKey ("latestVersion" )) continue ;
98
+ val modid = node .getString ("modid" );
99
+ if (!installedMods .containsKey (modid )) continue ;
100
+ val mod = installedMods .get (modid );
101
+ val latestVersionsNode = node .get ("latestVersion" );
102
+ List <String > latestVersions ;
103
+ if (latestVersionsNode .isString ()) {
104
+ latestVersions = Collections .singletonList (latestVersionsNode .stringValue ());
105
+ } else if (latestVersionsNode .isList ()) {
106
+ latestVersions = new ArrayList <>();
107
+ for (val version : latestVersionsNode .getJavaList ()) {
108
+ if (!version .isString ()) continue ;
109
+ latestVersions .add (version .stringValue ());
110
+ }
111
+ } else {
112
+ continue ;
113
+ }
114
+ val currentVersion = mod .getVersion ();
115
+ if (latestVersions .contains (currentVersion )) continue ;
116
+ val updateURL = node .containsKey ("updateURL" ) && node .get ("updateURL" ).isString () ? node .getString ("updateURL" ) : "" ;
117
+ result .add (new ModUpdateInfo (modid , currentVersion , latestVersions .get (0 ), updateURL ));
118
+ }
119
+ return result ;
120
+ });
121
+ }
122
+
123
+ /**
124
+ * Same this as {@link #fetchUpdatesAsync(String)}, but returns the result in a blocking fashion.
125
+ * @param url The URL to check
126
+ * @return A future that will contain the update info about mods that were both available on the URL and installed
127
+ * @throws UpdateCheckException If the update checker is disabled in config, the URL is invalid, or
128
+ */
129
+ public static List <ModUpdateInfo > fetchUpdates (String url ) throws UpdateCheckException {
130
+ try {
131
+ return fetchUpdatesAsync (url ).join ();
132
+ } catch (CompletionException e ) {
133
+ try {
134
+ throw e .getCause ();
135
+ } catch (UpdateCheckException e1 ) {
136
+ throw e1 ;
137
+ } catch (Throwable e1 ) {
138
+ throw new UpdateCheckException ("Failed to check for updates!" , e1 );
137
139
}
138
- val currentVersion = mod .getVersion ();
139
- if (latestVersions .contains (currentVersion )) continue ;
140
- val updateURL = node .containsKey ("updateURL" ) && node .get ("updateURL" ).isString () ? node .getString ("updateURL" ) : "" ;
141
- result .add (new ModUpdateInfo (modid , currentVersion , latestVersions .get (0 ), updateURL ));
142
140
}
143
- return result ;
144
141
}
145
142
146
143
/**
0 commit comments