diff --git a/src/main/java/net/raphimc/viaproxy/ViaProxy.java b/src/main/java/net/raphimc/viaproxy/ViaProxy.java index e54cae7..ab76c16 100644 --- a/src/main/java/net/raphimc/viaproxy/ViaProxy.java +++ b/src/main/java/net/raphimc/viaproxy/ViaProxy.java @@ -1,5 +1,7 @@ package net.raphimc.viaproxy; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; import io.netty.channel.Channel; import io.netty.channel.group.ChannelGroup; import io.netty.channel.group.DefaultChannelGroup; @@ -27,6 +29,9 @@ import net.raphimc.viaproxy.util.logging.Logger; import javax.swing.*; import java.awt.*; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; public class ViaProxy { @@ -34,8 +39,6 @@ public class ViaProxy { public static SaveManager saveManager; public static NetServer currentProxyServer; - public static Thread loaderThread; - public static Thread accountRefreshThread; public static ChannelGroup c2pChannels; public static void main(String[] args) throws Throwable { @@ -51,6 +54,7 @@ public class ViaProxy { public static void injectedMain(String[] args) throws InterruptedException { Logger.setup(); + final boolean hasUI = args.length == 0 && !GraphicsEnvironment.isHeadless(); ConsoleHandler.hookConsole(); Logger.LOGGER.info("Initializing ViaProxy v" + VERSION + "..."); saveManager = new SaveManager(); @@ -58,19 +62,52 @@ public class ViaProxy { setNettyParameters(); MCPipeline.useOptimizedPipeline(); c2pChannels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); - loaderThread = new Thread(() -> { + Thread loaderThread = new Thread(() -> { ProtocolHack.init(); PluginManager.loadPlugins(); }, "ViaProtocolHack-Loader"); - accountRefreshThread = new Thread(() -> { + Thread accountRefreshThread = new Thread(() -> { saveManager.accountsSave.refreshAccounts(); }, "AccountRefresh"); + Thread updateCheckThread = new Thread(() -> { + if (VERSION.startsWith("$")) return; // Dev env check + try { + URL url = new URL("https://api.github.com/repos/RaphiMC/ViaProxy/releases/latest"); + HttpURLConnection con = (HttpURLConnection) url.openConnection(); + con.setRequestMethod("GET"); + con.setRequestProperty("User-Agent", "ViaProxy/" + VERSION); + con.setConnectTimeout(5000); + con.setReadTimeout(5000); - if (args.length == 0 && !GraphicsEnvironment.isHeadless()) { + InputStream in = con.getInputStream(); + byte[] bytes = new byte[1024]; + int read; + StringBuilder builder = new StringBuilder(); + while ((read = in.read(bytes)) != -1) builder.append(new String(bytes, 0, read)); + con.disconnect(); + + JsonObject object = JsonParser.parseString(builder.toString()).getAsJsonObject(); + String latestVersion = object.get("tag_name").getAsString().substring(1); + if (!VERSION.equals(latestVersion)) { + Logger.LOGGER.warn("You are running an outdated version of ViaProxy! Latest version: " + latestVersion); + if (hasUI) { + SwingUtilities.invokeLater(() -> { + JFrame frontFrame = new JFrame(); + frontFrame.setAlwaysOnTop(true); + JOptionPane.showMessageDialog(frontFrame, "You are running an outdated version of ViaProxy!\nCurrent version: " + VERSION + "\nLatest version: " + latestVersion, "ViaProxy", JOptionPane.WARNING_MESSAGE); + }); + } + } + } catch (Throwable ignored) { + } + }, "UpdateCheck"); + + if (hasUI) { loaderThread.start(); accountRefreshThread.start(); final ViaProxyUI[] ui = new ViaProxyUI[1]; SwingUtilities.invokeLater(() -> ui[0] = new ViaProxyUI()); + updateCheckThread.start(); loaderThread.join(); accountRefreshThread.join(); ui[0].setReady(); @@ -85,6 +122,7 @@ public class ViaProxy { System.exit(0); } + updateCheckThread.start(); loaderThread.start(); loaderThread.join(); Logger.LOGGER.info("ViaProxy started successfully!"); diff --git a/src/main/java/net/raphimc/viaproxy/saves/impl/AccountsSave.java b/src/main/java/net/raphimc/viaproxy/saves/impl/AccountsSave.java index fad098f..6df3054 100644 --- a/src/main/java/net/raphimc/viaproxy/saves/impl/AccountsSave.java +++ b/src/main/java/net/raphimc/viaproxy/saves/impl/AccountsSave.java @@ -1,6 +1,8 @@ package net.raphimc.viaproxy.saves.impl; -import com.google.gson.*; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; import net.raphimc.mcauth.MinecraftAuth; import net.raphimc.mcauth.step.java.StepGameOwnership; import net.raphimc.mcauth.step.java.StepMCProfile; @@ -9,7 +11,10 @@ import net.raphimc.viaproxy.saves.AbstractSave; import net.raphimc.viaproxy.util.logging.Logger; import org.apache.http.impl.client.CloseableHttpClient; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.UUID; public class AccountsSave extends AbstractSave { @@ -48,16 +53,18 @@ public class AccountsSave extends AbstractSave { return array; } - public void addAccount(final StepMCProfile.MCProfile profile) { + public StepMCProfile.MCProfile addAccount(final StepMCProfile.MCProfile profile) { this.accounts.add(profile); + return profile; } - public void addAccount(final int index, final StepMCProfile.MCProfile profile) { + public StepMCProfile.MCProfile addAccount(final int index, final StepMCProfile.MCProfile profile) { this.accounts.add(index, profile); + return profile; } - public void addOfflineAccount(final String name) { - this.addAccount(new StepMCProfile.MCProfile(UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes()), name, null, new StepGameOwnership.GameOwnership(Collections.emptyList(), null))); + public StepMCProfile.MCProfile addOfflineAccount(final String name) { + return this.addAccount(new StepMCProfile.MCProfile(UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes()), name, null, new StepGameOwnership.GameOwnership(Collections.emptyList(), null))); } public void removeAccount(final StepMCProfile.MCProfile profile) { diff --git a/src/main/java/net/raphimc/viaproxy/ui/impl/GeneralTab.java b/src/main/java/net/raphimc/viaproxy/ui/impl/GeneralTab.java index 65328c8..9fd04bb 100644 --- a/src/main/java/net/raphimc/viaproxy/ui/impl/GeneralTab.java +++ b/src/main/java/net/raphimc/viaproxy/ui/impl/GeneralTab.java @@ -94,7 +94,7 @@ public class GeneralTab extends AUITab { authMethodLabel.setBounds(10, 200, 400, 20); contentPane.add(authMethodLabel); - this.authMethod = new JComboBox<>(new String[]{"Use stored account", "Use OpenAuthMod"}); + this.authMethod = new JComboBox<>(new String[]{"Use selected account", "Use OpenAuthMod"}); this.authMethod.setBounds(10, 220, 465, 20); contentPane.add(this.authMethod); } diff --git a/src/main/java/net/raphimc/viaproxy/ui/impl/OnlineModeTab.java b/src/main/java/net/raphimc/viaproxy/ui/impl/OnlineModeTab.java index d809284..e91e134 100644 --- a/src/main/java/net/raphimc/viaproxy/ui/impl/OnlineModeTab.java +++ b/src/main/java/net/raphimc/viaproxy/ui/impl/OnlineModeTab.java @@ -18,13 +18,13 @@ import java.util.concurrent.TimeoutException; public class OnlineModeTab extends AUITab { private JList accountsList; - private JButton addAccountButton; + private JButton addMicrosoftAccountButton; private AddAccountPopup addAccountPopup; private Thread addThread; public OnlineModeTab(final ViaProxyUI frame) { - super(frame, "Online Mode"); + super(frame, "Accounts"); } @Override @@ -91,7 +91,7 @@ public class OnlineModeTab extends AUITab { JPopupMenu contextMenu = new JPopupMenu(); { - JMenuItem selectItem = new JMenuItem("Use to join online mode servers"); + JMenuItem selectItem = new JMenuItem("Select account"); selectItem.addActionListener(e -> { int index = this.accountsList.getSelectedIndex(); if (index != -1) this.markSelected(index); @@ -141,10 +141,23 @@ public class OnlineModeTab extends AUITab { this.accountsList.setComponentPopupMenu(contextMenu); } { - this.addAccountButton = new JButton("Add Account"); - this.addAccountButton.setBounds(300, 300, 175, 20); - this.addAccountButton.addActionListener(event -> { - this.addAccountButton.setEnabled(false); + JButton addOfflineAccountButton = new JButton("Add Offline Account"); + addOfflineAccountButton.setBounds(10, 300, 230, 20); + addOfflineAccountButton.addActionListener(event -> { + String username = JOptionPane.showInputDialog(this.frame, "Enter your offline mode Username:", "Add Offline Account", JOptionPane.PLAIN_MESSAGE); + if (username != null) { + StepMCProfile.MCProfile account = ViaProxy.saveManager.accountsSave.addOfflineAccount(username); + ViaProxy.saveManager.save(); + this.addAccount(account); + } + }); + contentPane.add(addOfflineAccountButton); + } + { + this.addMicrosoftAccountButton = new JButton("Add Microsoft Account"); + this.addMicrosoftAccountButton.setBounds(245, 300, 230, 20); + this.addMicrosoftAccountButton.addActionListener(event -> { + this.addMicrosoftAccountButton.setEnabled(false); this.addThread = new Thread(() -> { try { StepMCProfile.MCProfile profile = MinecraftAuth.requestJavaLogin(msaDeviceCode -> { @@ -159,8 +172,7 @@ public class OnlineModeTab extends AUITab { this.closePopup(); ViaProxy.saveManager.accountsSave.addAccount(profile); ViaProxy.saveManager.save(); - DefaultListModel model = (DefaultListModel) this.accountsList.getModel(); - model.addElement(profile.name()); + this.addAccount(profile); this.frame.showInfo("The account " + profile.name() + " was added successfully."); }); } catch (InterruptedException ignored) { @@ -179,14 +191,14 @@ public class OnlineModeTab extends AUITab { this.addThread.setDaemon(true); this.addThread.start(); }); - contentPane.add(this.addAccountButton); + contentPane.add(this.addMicrosoftAccountButton); } } @Override public void setReady() { - final DefaultListModel model = (DefaultListModel) this.accountsList.getModel(); - ViaProxy.saveManager.accountsSave.getAccounts().forEach(account -> model.addElement(account.name())); + ViaProxy.saveManager.accountsSave.getAccounts().forEach(this::addAccount); + DefaultListModel model = (DefaultListModel) this.accountsList.getModel(); if (!model.isEmpty()) this.markSelected(0); } @@ -195,7 +207,13 @@ public class OnlineModeTab extends AUITab { this.addAccountPopup.setVisible(false); this.addAccountPopup.dispose(); this.addAccountPopup = null; - this.addAccountButton.setEnabled(true); + this.addMicrosoftAccountButton.setEnabled(true); + } + + private void addAccount(final StepMCProfile.MCProfile account) { + DefaultListModel model = (DefaultListModel) this.accountsList.getModel(); + if (account.prevResult().items().isEmpty()) model.addElement(account.name() + " (Offline)"); + else model.addElement(account.name() + " (Microsoft)"); } private void markSelected(final int index) {