Skip to content

Commit 6a409b6

Browse files
committed
stage2/ml9: create mixin bootstrap
1 parent 65ec87d commit 6a409b6

File tree

3 files changed

+165
-0
lines changed

3 files changed

+165
-0
lines changed
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package gg.essential.loader.stage2;
2+
3+
import com.google.gson.JsonElement;
4+
import com.google.gson.JsonObject;
5+
import com.google.gson.JsonParser;
6+
7+
import java.io.IOException;
8+
import java.io.InputStream;
9+
import java.io.OutputStream;
10+
import java.net.URL;
11+
import java.net.URLConnection;
12+
import java.nio.file.Files;
13+
import java.nio.file.Path;
14+
15+
public class DedicatedJarLoader {
16+
private static final String BASE_URL = System.getProperty(
17+
"essential.download.url",
18+
System.getenv().getOrDefault("ESSENTIAL_DOWNLOAD_URL", "https://api.essential.gg/mods")
19+
);
20+
private static final String VERSION_URL = BASE_URL + "/v1/essential:essential-pinned/versions/stable/platforms/%s";
21+
private static final String DOWNLOAD_URL = VERSION_URL + "/download";
22+
23+
protected static void downloadDedicatedJar(LoaderUI ui, Path modsDir, String gameVersion) throws IOException {
24+
final JsonObject meta = getEssentialDownloadMeta(gameVersion);
25+
final URL url = new URL(meta.get("url").getAsString());
26+
final URLConnection connection = url.openConnection();
27+
28+
ui.setDownloadSize(connection.getContentLength());
29+
30+
final String essentialVersion = getEssentialVersionMeta(gameVersion).get("version").getAsString();
31+
final Path target = modsDir.resolve(String.format("Essential %s (%s).jar", gameVersion, essentialVersion));
32+
33+
try (
34+
final InputStream in = connection.getInputStream();
35+
final OutputStream out = Files.newOutputStream(target);
36+
) {
37+
38+
final byte[] buffer = new byte[1024];
39+
int totalRead = 0;
40+
int read;
41+
while ((read = in.read(buffer)) != -1) {
42+
out.write(buffer, 0, read);
43+
totalRead += read;
44+
ui.setDownloaded(totalRead);
45+
}
46+
}
47+
}
48+
49+
private static JsonObject getEssentialMeta(URL url) throws IOException {
50+
String response;
51+
try (final InputStream in = url.openStream()) {
52+
response = new String(in.readAllBytes());
53+
}
54+
JsonElement json = new JsonParser().parse(response);
55+
return json.getAsJsonObject();
56+
}
57+
58+
private static JsonObject getEssentialVersionMeta(String gameVersion) throws IOException {
59+
return getEssentialMeta(new URL(String.format(VERSION_URL, gameVersion)));
60+
}
61+
62+
private static JsonObject getEssentialDownloadMeta(String gameVersion) throws IOException {
63+
return getEssentialMeta(new URL(String.format(DOWNLOAD_URL, gameVersion)));
64+
}
65+
}

stage2/modlauncher9/src/main/java/gg/essential/loader/stage2/EssentialLoader.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package gg.essential.loader.stage2;
22

33
import cpw.mods.modlauncher.api.ITransformationService;
4+
import gg.essential.loader.stage2.jvm.ForkedJvmLoaderSwingUI;
5+
import net.minecraftforge.fml.loading.FMLLoader;
46

7+
import java.io.IOException;
58
import java.nio.file.Path;
69

710
/**
@@ -26,4 +29,20 @@ public ITransformationService getTransformationService() {
2629
public void load() {
2730
// delayed until ModLauncher exposes the MC version
2831
}
32+
33+
@SuppressWarnings("unused") // called via reflection from stage1
34+
public void loadFromMixin(Path gameDir) throws IOException {
35+
final Path modsDir = gameDir.resolve("mods");
36+
LoaderUI ui = LoaderUI.all(
37+
new LoaderLoggingUI().updatesEveryMillis(1000),
38+
new ForkedJvmLoaderSwingUI().updatesEveryMillis(1000 / 60)
39+
);
40+
ui.start();
41+
DedicatedJarLoader.downloadDedicatedJar(ui, modsDir, "forge_" + FMLLoader.versionInfo().mcVersion());
42+
ui.complete();
43+
RestartUI restartUI = new RestartUI("Restart Required!", "One of the mods you have installed requires Essential. To complete the installation process, please restart.");
44+
restartUI.show();
45+
restartUI.waitForClose();
46+
System.exit(0);
47+
}
2948
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package gg.essential.loader.stage2;
2+
3+
import gg.essential.loader.stage2.components.EssentialStyle;
4+
5+
import javax.swing.*;
6+
import javax.swing.border.EmptyBorder;
7+
import java.awt.*;
8+
import java.util.ArrayList;
9+
import java.util.List;
10+
import java.util.concurrent.CompletableFuture;
11+
12+
import static gg.essential.loader.stage2.components.ButtonShadowBorder.X_SHADOW;
13+
import static gg.essential.loader.stage2.components.ButtonShadowBorder.Y_SHADOW;
14+
15+
public class RestartUI implements EssentialStyle {
16+
private final CompletableFuture<Boolean> closedFuture = new CompletableFuture<>();
17+
18+
private final JFrame frame = makeFrame(it -> closedFuture.complete(null));
19+
20+
private final String title;
21+
private final String description;
22+
23+
public RestartUI(String title, String description) {
24+
this.title = title;
25+
this.description = description;
26+
}
27+
28+
public void show() {
29+
final List<JLabel> htmlLabels = new ArrayList<>();
30+
31+
final JPanel content = makeContent(frame);
32+
content.setBorder(new EmptyBorder(0, 60 - X_SHADOW, 0, 60 - X_SHADOW));
33+
content.add(Box.createHorizontalStrut(CONTENT_WIDTH));
34+
35+
htmlLabels.add(makeTitle(content, html(centered(title))));
36+
37+
final JLabel explanation = new JLabel(html(centered(description)), SwingConstants.CENTER);
38+
explanation.setMaximumSize(new Dimension(CONTENT_WIDTH, Integer.MAX_VALUE));
39+
explanation.setForeground(COLOR_FOREGROUND);
40+
explanation.setAlignmentX(Container.CENTER_ALIGNMENT);
41+
if (Fonts.medium != null) {
42+
explanation.setFont(Fonts.medium.deriveFont(16F));
43+
}
44+
content.add(explanation);
45+
htmlLabels.add(explanation);
46+
47+
content.add(Box.createVerticalStrut(32 - Y_SHADOW));
48+
49+
final JPanel buttons = new JPanel();
50+
buttons.setOpaque(false);
51+
buttons.setLayout(new BoxLayout(buttons, BoxLayout.X_AXIS));
52+
buttons.add(makeButton("Restart", COLOR_PRIMARY_BUTTON, COLOR_BUTTON_HOVER, () -> closedFuture.complete(true)));
53+
content.add(buttons);
54+
55+
content.add(Box.createVerticalStrut(32 - Y_SHADOW));
56+
57+
frame.pack();
58+
59+
htmlLabels.forEach(this::fixJLabelHeight);
60+
frame.pack();
61+
62+
frame.setLocationRelativeTo(null);
63+
frame.setVisible(true);
64+
}
65+
66+
public Boolean waitForClose() {
67+
Boolean verdict = closedFuture.join();
68+
close();
69+
return verdict;
70+
}
71+
72+
public void close() {
73+
frame.dispose();
74+
}
75+
76+
public static void main(String[] args) {
77+
RestartUI ui = new RestartUI("Restart required!", "A restart is required for something.");
78+
ui.show();
79+
System.out.println(ui.waitForClose());
80+
}
81+
}

0 commit comments

Comments
 (0)