From af0d75923eed626a842b62e5ba198ce3e2444956 Mon Sep 17 00:00:00 2001 From: Samuel Rapana Betio Date: Wed, 23 Aug 2017 09:38:55 +0800 Subject: [PATCH 1/6] Add files via upload --- Copyright.md | 13 + README.md | 13 +- .../sleitnick/roblox/launcher/Browser.java | 58 +++++ .../roblox/launcher/DataStoreService.java | 94 ++++++++ .../roblox/launcher/HttpService.java | 54 +++++ .../launcher/IntegerDocumentFilter.java | 56 +++++ .../roblox/launcher/LuaFileException.java | 22 ++ .../sleitnick/roblox/launcher/LuaScript.java | 70 ++++++ .../roblox/launcher/RobloxLauncher.java | 65 +++++ .../roblox/launcher/RobloxLauncherApp.java | 227 ++++++++++++++++++ .../roblox/launcher/RobloxPlace.java | 132 ++++++++++ .../roblox/launcher/RobloxPlaceException.java | 48 ++++ .../launcher/RobloxVersionException.java | 26 ++ .../src/sleitnick/roblox/launcher/icon.png | Bin 0 -> 2466 bytes .../src/sleitnick/roblox/launcher/logo.png | Bin 0 -> 7975 bytes .../roblox/launcher/parse_place_response.lua | 42 ++++ 16 files changed, 918 insertions(+), 2 deletions(-) create mode 100644 Copyright.md create mode 100644 RobloxLauncher/src/sleitnick/roblox/launcher/Browser.java create mode 100644 RobloxLauncher/src/sleitnick/roblox/launcher/DataStoreService.java create mode 100644 RobloxLauncher/src/sleitnick/roblox/launcher/HttpService.java create mode 100644 RobloxLauncher/src/sleitnick/roblox/launcher/IntegerDocumentFilter.java create mode 100644 RobloxLauncher/src/sleitnick/roblox/launcher/LuaFileException.java create mode 100644 RobloxLauncher/src/sleitnick/roblox/launcher/LuaScript.java create mode 100644 RobloxLauncher/src/sleitnick/roblox/launcher/RobloxLauncher.java create mode 100644 RobloxLauncher/src/sleitnick/roblox/launcher/RobloxLauncherApp.java create mode 100644 RobloxLauncher/src/sleitnick/roblox/launcher/RobloxPlace.java create mode 100644 RobloxLauncher/src/sleitnick/roblox/launcher/RobloxPlaceException.java create mode 100644 RobloxLauncher/src/sleitnick/roblox/launcher/RobloxVersionException.java create mode 100644 RobloxLauncher/src/sleitnick/roblox/launcher/icon.png create mode 100644 RobloxLauncher/src/sleitnick/roblox/launcher/logo.png create mode 100644 RobloxLauncher/src/sleitnick/roblox/launcher/parse_place_response.lua diff --git a/Copyright.md b/Copyright.md new file mode 100644 index 0000000..d4a81b4 --- /dev/null +++ b/Copyright.md @@ -0,0 +1,13 @@ +Copyright 2014 Stephen Leitnick + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md index 576ca67..7700d09 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,11 @@ -# RobloxLauncher -A RobloxLauncher made using the RobloxProxy.dll. and Launch ROBLOX without the website, given the Place ID. +RobloxLauncher +============== + +Launch ROBLOX without the website, given the Place ID. + +Requires Java 1.6 or newer. + + +I created this application because I can no longer launch ROBLOX games from their website (on any browser). When I attempt to, +the ROBLOX updater window would pop up and sit there for several minutes, but never would launch the game. This application +shortcuts the process and launches the game by itself. diff --git a/RobloxLauncher/src/sleitnick/roblox/launcher/Browser.java b/RobloxLauncher/src/sleitnick/roblox/launcher/Browser.java new file mode 100644 index 0000000..353388f --- /dev/null +++ b/RobloxLauncher/src/sleitnick/roblox/launcher/Browser.java @@ -0,0 +1,58 @@ +package sleitnick.roblox.launcher; + +import java.awt.Desktop; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; + +public final class Browser { + + private static final Desktop DESKTOP = Desktop.isDesktopSupported() ? Desktop.getDesktop() : null; + + /** + * Check if Browser support is available + * @return isSupported + */ + public static boolean isSupported() { + return DESKTOP.isSupported(Desktop.Action.BROWSE); + } + + /** + * Browse to the given URI + * @param uri {@link URI} + */ + public static void browse(URI uri) { + try { + DESKTOP.browse(uri); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * Browse to the given URL + * @param url {@link URL} + */ + public static void browse(URL url) { + try { + browse(url.toURI()); + } catch (URISyntaxException e) { + e.printStackTrace(); + } + } + + /** + * Browse to the given URL + * @param url {@link String} URL + */ + public static void browse(String url) { + try { + browse(new URL(url)); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + } + +} diff --git a/RobloxLauncher/src/sleitnick/roblox/launcher/DataStoreService.java b/RobloxLauncher/src/sleitnick/roblox/launcher/DataStoreService.java new file mode 100644 index 0000000..d2e3b56 --- /dev/null +++ b/RobloxLauncher/src/sleitnick/roblox/launcher/DataStoreService.java @@ -0,0 +1,94 @@ +package sleitnick.roblox.launcher; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; + +public final class DataStoreService { + + private static final class Data implements Serializable { + private static final long serialVersionUID = 1L; + private final Map data = new HashMap(); + } + + private static final String DATA_DIR_NAME = "data"; + private static final String DATA_FILE_NAME = "data.ser"; + + private static Data data = null; + + // Load data: + static { + File dataDir = new File(DATA_DIR_NAME); + if (dataDir.isDirectory()) { + File dataFile = new File(dataDir, DATA_FILE_NAME); + try { + FileInputStream fis = new FileInputStream(dataFile); + ObjectInputStream ois = new ObjectInputStream(fis); + Object objData = ois.readObject(); + ois.close(); + fis.close(); + if (objData instanceof Data) { + data = (Data)objData; + } + } catch (Exception e) { + } + } else { + dataDir.mkdir(); + } + if (data == null) { + data = new Data(); + } + } + + /** + * Set a value in the data store + * @param key {@link String} key + * @param value Value + */ + protected static void set(String key, Object value) { + data.data.put(key, value); + } + + /** + * Get value from given key + * @param key {@link String} key + * @return {@link Object} Value + */ + protected static Object get(String key) { + return data.data.get(key); + } + + /** + * Save the data in the data store + */ + protected static void save() { + File dataDir = new File(DATA_DIR_NAME); + if (!dataDir.isDirectory()) { + dataDir.mkdir(); + } + File dataFile = new File(dataDir, DATA_FILE_NAME); + if (!dataFile.exists()) { + try { + dataFile.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + } + try { + FileOutputStream fos = new FileOutputStream(dataFile); + ObjectOutputStream oos = new ObjectOutputStream(fos); + oos.writeObject(data); + oos.close(); + fos.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } + +} diff --git a/RobloxLauncher/src/sleitnick/roblox/launcher/HttpService.java b/RobloxLauncher/src/sleitnick/roblox/launcher/HttpService.java new file mode 100644 index 0000000..7cf27c7 --- /dev/null +++ b/RobloxLauncher/src/sleitnick/roblox/launcher/HttpService.java @@ -0,0 +1,54 @@ +package sleitnick.roblox.launcher; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; + +public final class HttpService { + + private static final Map RESPONSE_CACHE = new HashMap(); + + /** + * Get the HTTP response from the given URL. + * @param urlStr {@link String} URL + * @param cacheResponse Whether or not to cache the response + * @return {@link String} response + */ + public static final String get(String urlStr, boolean cacheResponse) { + if (cacheResponse) { + String fromCache = RESPONSE_CACHE.get(urlStr); + if (fromCache != null) { + return fromCache; + } + } + URL url; + HttpURLConnection conn; + BufferedReader rd; + String line; + String result = ""; + try { + url = new URL(urlStr); + conn = (HttpURLConnection)url.openConnection(); + conn.setRequestMethod("GET"); + rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); + while ((line = rd.readLine()) != null) { + result += line; + } + rd.close(); + } catch(IOException e) { + result = ""; + } catch(Exception e) { + result = ""; + } + if (cacheResponse) { + RESPONSE_CACHE.put(urlStr, result); + } + return result; + } + + +} diff --git a/RobloxLauncher/src/sleitnick/roblox/launcher/IntegerDocumentFilter.java b/RobloxLauncher/src/sleitnick/roblox/launcher/IntegerDocumentFilter.java new file mode 100644 index 0000000..28c4fb2 --- /dev/null +++ b/RobloxLauncher/src/sleitnick/roblox/launcher/IntegerDocumentFilter.java @@ -0,0 +1,56 @@ +package sleitnick.roblox.launcher; + +import javax.swing.text.AttributeSet; +import javax.swing.text.BadLocationException; +import javax.swing.text.Document; +import javax.swing.text.DocumentFilter; + +public class IntegerDocumentFilter extends DocumentFilter { + + private boolean isUnsignedInteger(String str) { + if (str.isEmpty()) return true; + try { + Integer.parseUnsignedInt(str); + return true; + } catch(NumberFormatException e) { + return false; + } + } + + @Override + public void insertString(FilterBypass fb, int offset, String string, + AttributeSet attr) throws BadLocationException { + Document doc = fb.getDocument(); + StringBuilder sb = new StringBuilder(); + sb.append(doc.getText(0, doc.getLength())); + sb.insert(offset, string); + if (isUnsignedInteger(sb.toString())) { + super.insertString(fb, offset, string, attr); + } + } + + @Override + public void remove(FilterBypass fb, int offset, int length) + throws BadLocationException { + Document doc = fb.getDocument(); + StringBuilder sb = new StringBuilder(); + sb.append(doc.getText(0, doc.getLength())); + sb.delete(offset, offset + length); + if (isUnsignedInteger(sb.toString())) { + super.remove(fb, offset, length); + } + } + + @Override + public void replace(FilterBypass fb, int offset, int length, String text, + AttributeSet attrs) throws BadLocationException { + Document doc = fb.getDocument(); + StringBuilder sb = new StringBuilder(); + sb.append(doc.getText(0, doc.getLength())); + sb.replace(offset, offset + length, text); + if (isUnsignedInteger(sb.toString())) { + super.replace(fb, offset, length, text, attrs); + } + } + +} diff --git a/RobloxLauncher/src/sleitnick/roblox/launcher/LuaFileException.java b/RobloxLauncher/src/sleitnick/roblox/launcher/LuaFileException.java new file mode 100644 index 0000000..2971a9c --- /dev/null +++ b/RobloxLauncher/src/sleitnick/roblox/launcher/LuaFileException.java @@ -0,0 +1,22 @@ +package sleitnick.roblox.launcher; + +public class LuaFileException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + private final String msg; + + public LuaFileException() { + this("Lua file exception"); + } + + public LuaFileException(String msg) { + this.msg = msg; + } + + @Override + public String getMessage() { + return msg; + } + +} diff --git a/RobloxLauncher/src/sleitnick/roblox/launcher/LuaScript.java b/RobloxLauncher/src/sleitnick/roblox/launcher/LuaScript.java new file mode 100644 index 0000000..1ec236b --- /dev/null +++ b/RobloxLauncher/src/sleitnick/roblox/launcher/LuaScript.java @@ -0,0 +1,70 @@ +package sleitnick.roblox.launcher; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; + +import org.luaj.vm2.Globals; +import org.luaj.vm2.LuaValue; +import org.luaj.vm2.lib.jse.JsePlatform; + + + +public class LuaScript { + + private static final ArrayList LUA_VALID_EXT = new ArrayList() { + private static final long serialVersionUID = 1L; + { + this.add(".lua"); + this.add(".txt"); + } + }; + + private static String getSourceFromStream(InputStream stream) throws IOException { + StringBuilder sb = new StringBuilder(); + int ch; + while ((ch = stream.read()) != -1) { + sb.append((char)ch); + } + return sb.toString(); + } + + private String source; + + private boolean isValidName(String name) { + name = name.toLowerCase(); + for (String ext : LUA_VALID_EXT) { + if (name.endsWith(ext.toLowerCase())) { + return true; + } + } + return false; + } + + /** + * Create a Lua script from the given name + *

+ * Will search the class for the given file + * @param name Script name + */ + public LuaScript(String name) { + if (!isValidName(name)) { + throw new LuaFileException("Wrong Lua file type"); + } + InputStream stream = getClass().getResourceAsStream(name); + try { + String source = getSourceFromStream(stream); + this.source = source; + } catch(IOException e) { + e.printStackTrace(); + } + } + + public LuaValue execute(String url) { + Globals _G = JsePlatform.standardGlobals(); + _G.set("httpResponse", url); + LuaValue chunk = _G.load(source); + return chunk.call(); + } + +} diff --git a/RobloxLauncher/src/sleitnick/roblox/launcher/RobloxLauncher.java b/RobloxLauncher/src/sleitnick/roblox/launcher/RobloxLauncher.java new file mode 100644 index 0000000..807a369 --- /dev/null +++ b/RobloxLauncher/src/sleitnick/roblox/launcher/RobloxLauncher.java @@ -0,0 +1,65 @@ +package sleitnick.roblox.launcher; + +import java.awt.Frame; +import java.io.File; +import java.io.IOException; + +public final class RobloxLauncher { + + public static final String URL_ROBLOX_VERSION = "http://setup.roblox.com/version"; + public static final String URL_REQUEST_GAME = "http://www.roblox.com/Game/PlaceLauncher.ashx?request=RequestGame&placeId=#ID"; + public static final String URL_REQUEST_GROUP_BUILD_GAME = "http://www.roblox.com/Game/PlaceLauncher.ashx?request=RequestGroupBuildGame&placeId=#ID"; + public static final String URL_DOWNLOAD_ROBLOX = "http://www.roblox.com/install/setup.ashx"; + + private static String robloxVersion; + static { + String response = HttpService.get(URL_ROBLOX_VERSION, false); + robloxVersion = response; + } + + private static final String LOCAL_APP_DATA = System.getenv("LOCALAPPDATA"); + private static final File RBX_DIR = new File(LOCAL_APP_DATA, "Roblox/Versions/" + robloxVersion); + + + /** + * Current version installed + * @return true if current version is installed + */ + public static boolean hasCurrentVersion() { + return RBX_DIR.exists(); + } + + /** + * Launch the given place + * @param place Place to launch + * @param frame Frame to launch from + * @throws RobloxVersionException + */ + protected static void launch(RobloxPlace place, Frame frame) throws RobloxVersionException { + + if (!hasCurrentVersion()) { + throw new RobloxVersionException(); + } + + String joinRequest = HttpService.get((place.isPersonalServer() ? URL_REQUEST_GROUP_BUILD_GAME : URL_REQUEST_GAME).replaceAll("#ID", Integer.toString(place.getPlaceId())), false); + + if (joinRequest.contains("JoinPlace=") || joinRequest.contains("Game/Join.ashx")) { + frame.setVisible(false); + try { + String launchCmd = (RBX_DIR.getAbsolutePath() + "/RobloxPlayerBeta.exe --id " + place.getPlaceId()); + Process rbxProcess = Runtime.getRuntime().exec(launchCmd); + rbxProcess.waitFor(); + } catch (IOException e) { + e.printStackTrace(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + frame.setVisible(true); + } else { + System.out.println("Join request failed"); + System.out.println(joinRequest); + } + + } + +} diff --git a/RobloxLauncher/src/sleitnick/roblox/launcher/RobloxLauncherApp.java b/RobloxLauncher/src/sleitnick/roblox/launcher/RobloxLauncherApp.java new file mode 100644 index 0000000..785e642 --- /dev/null +++ b/RobloxLauncher/src/sleitnick/roblox/launcher/RobloxLauncherApp.java @@ -0,0 +1,227 @@ +package sleitnick.roblox.launcher; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Cursor; +import java.awt.Font; +import java.awt.Image; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.net.URL; + +import javax.swing.BoxLayout; +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JSeparator; +import javax.swing.JTextField; +import javax.swing.UIManager; +import javax.swing.border.EmptyBorder; +import javax.swing.text.PlainDocument; + +public class RobloxLauncherApp implements ActionListener { + + private JFrame frame; + private JPanel panel; + private JPanel gamePanel; + private JLabel logoLabel; + private JLabel idLabel; + private JTextField idField; + private JButton searchButton; + private JLabel gameTitle, gameCreator; + private JLabel gameImage; + private JButton launchButton; + private JButton launchBrowserButton; + + private final Color background = new Color(75, 75, 75); + + private final String ID_INPUT_KEY = "idInput"; + + private RobloxPlace currentSearch = null; + + private void createGui() { + frame = new JFrame("ROBLOX Launcher"); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setResizable(false); + frame.getContentPane().setBackground(background); + panel = new JPanel(); + panel.setBorder(new EmptyBorder(10, 10, 10, 10)); + panel.setBackground(background); + gamePanel = new JPanel(); + gamePanel.setBorder(new EmptyBorder(10, 10, 10, 10)); + gamePanel.setLayout(new BoxLayout(gamePanel, BoxLayout.PAGE_AXIS)); + gamePanel.setBackground(background); + frame.getContentPane().add(panel, BorderLayout.CENTER); + frame.getContentPane().add(gamePanel, BorderLayout.SOUTH); + URL logoURL = getClass().getResource("logo.png"); + ImageIcon logo = new ImageIcon(logoURL); + logoLabel = new JLabel(logo); + logoLabel.setBorder(new EmptyBorder(10, 10, 10, 10)); + idLabel = new JLabel("Place ID:"); + idLabel.setFont(new Font("Arial", Font.BOLD, 14)); + idLabel.setForeground(new Color(255, 255, 255)); + idField = new JTextField(20); + idField.setFont(new Font("Arial", Font.PLAIN, 12)); + { + Object idObj = DataStoreService.get(ID_INPUT_KEY); + if (idObj != null && idObj instanceof Integer) { + int id = (Integer)idObj; + idField.setText(Integer.toString(id)); + } + } + idLabel.setLabelFor(idField); + searchButton = new JButton("Search"); + searchButton.setBackground(background); + searchButton.setFont(new Font("Arial", Font.PLAIN, 12)); + frame.getContentPane().add(logoLabel, BorderLayout.NORTH); + panel.add(idLabel); + panel.add(idField); + panel.add(searchButton); + gameTitle = new JLabel(); + gameTitle.setBorder(new EmptyBorder(10, 0, 0, 0)); + gameTitle.setFont(new Font("Arial", Font.PLAIN, 18)); + gameTitle.setForeground(new Color(255, 255, 255)); + gameCreator = new JLabel(); + gameCreator.setFont(new Font("Arial", Font.PLAIN, 14)); + gameCreator.setForeground(new Color(255, 255, 255)); + gameImage = new JLabel(); + gameImage.setBorder(new EmptyBorder(10, 0, 10, 0)); + JSeparator sep = new JSeparator(JSeparator.HORIZONTAL); + sep.setBackground(new Color(100, 100, 100)); + sep.setForeground(background); + gamePanel.add(sep); + gamePanel.add(gameTitle); + gamePanel.add(gameCreator); + gamePanel.add(gameImage); + launchButton = new JButton("Play"); + launchButton.setBackground(background); + launchButton.setFont(new Font("Arial", Font.BOLD, 14)); + launchBrowserButton = new JButton("Open in Browser"); + launchBrowserButton.setBackground(background); + launchBrowserButton.setFont(new Font("Arial", Font.PLAIN, 14)); + gamePanel.add(launchBrowserButton); + gamePanel.add(launchButton); + frame.pack(); + frame.setLocation(100, 100); + URL iconURL = getClass().getResource("icon.png"); + ImageIcon icon = new ImageIcon(iconURL); + frame.setIconImage(icon.getImage()); + frame.addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + DataStoreService.save(); + super.windowClosing(e); + } + }); + frame.setVisible(true); + } + + private void setIdFieldIntegerOnly() { + PlainDocument doc = (PlainDocument)idField.getDocument(); + doc.setDocumentFilter(new IntegerDocumentFilter()); + } + + @Override + public void actionPerformed(ActionEvent e) { + if (e.getActionCommand().equals("launchGame")) { + if (!launchButton.isEnabled()) { + return; + } + String idStr = idField.getText().trim(); + if (!idStr.isEmpty()) { + int id = Integer.parseInt(idStr); + launchButton.setEnabled(false); + try { + RobloxPlace place = new RobloxPlace(id); + RobloxLauncher.launch(place, frame); + } catch(RobloxVersionException rbxVersionException) { + Browser.browse(RobloxLauncher.URL_DOWNLOAD_ROBLOX); + System.exit(0); + } catch (RobloxPlaceException e1) { + gameTitle.setText("Invalid place ID"); + gameCreator.setText(""); + gameImage.setIcon(null); + launchButton.setVisible(false); + launchBrowserButton.setVisible(false); + } + launchButton.setEnabled(true); + } + } else if (e.getActionCommand().equals("searchGame")) { + if (!idField.getText().isEmpty()) { + int id = Integer.parseInt(idField.getText()); + try { + frame.getContentPane().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + idField.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + RobloxPlace place = new RobloxPlace(id); + currentSearch = place; + gameTitle.setText(place.getPlaceName()); + gameCreator.setText("Creator: " + place.getCreator()); + try { + URL url = new URL(place.getThumbnail()); + ImageIcon gameIcon = new ImageIcon(url); + Image img = gameIcon.getImage(); + img = img.getScaledInstance((int)(img.getWidth(null) / 1.2f), (int)(img.getHeight(null) / 1.2f), Image.SCALE_SMOOTH); + gameIcon = new ImageIcon(img); + gameImage.setIcon(gameIcon); + } catch (Exception e1) { + gameImage.setIcon(null); + } + DataStoreService.set(ID_INPUT_KEY, id); + launchButton.setVisible(true); + launchBrowserButton.setVisible(true); + frame.pack(); + } catch (RobloxPlaceException e1) { + gameTitle.setText(e1.getFailedToConnect() ? "Cannot connect to ROBLOX" : "Invalid place ID"); + gameCreator.setText(""); + gameImage.setIcon(null); + launchButton.setVisible(false); + launchBrowserButton.setVisible(false); + } finally { + frame.getContentPane().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + idField.setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR)); + } + frame.pack(); + } + } else if (e.getActionCommand().equals("openInBrowser")) { + if (currentSearch != null) { + currentSearch.openInBrowser(); + } + } + } + + public RobloxLauncherApp() { + createGui(); + setIdFieldIntegerOnly(); + searchButton.setActionCommand("searchGame"); + searchButton.addActionListener(this); + launchButton.setActionCommand("launchGame"); + launchButton.addActionListener(this); + launchBrowserButton.setActionCommand("openInBrowser"); + launchBrowserButton.addActionListener(this); + idField.setActionCommand("searchGame"); + idField.addActionListener(this); + idField.requestFocus(); + idField.setCaretPosition(idField.getText().length()); + if (!idField.getText().isEmpty()) { + for (ActionListener listener : idField.getActionListeners()) { + listener.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "searchGame") { + private static final long serialVersionUID = 1L; + }); + } + } + } + + public static void main(String[] args) { + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch (Exception e) { + e.printStackTrace(); + } + new RobloxLauncherApp(); + } + +} diff --git a/RobloxLauncher/src/sleitnick/roblox/launcher/RobloxPlace.java b/RobloxLauncher/src/sleitnick/roblox/launcher/RobloxPlace.java new file mode 100644 index 0000000..f752b29 --- /dev/null +++ b/RobloxLauncher/src/sleitnick/roblox/launcher/RobloxPlace.java @@ -0,0 +1,132 @@ +package sleitnick.roblox.launcher; + +import java.io.Serializable; +import java.io.UnsupportedEncodingException; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.net.URLDecoder; + +import org.luaj.vm2.LuaValue; + + + +public class RobloxPlace implements Serializable { + + private static final long serialVersionUID = 1L; + private static final String PLACE_URL = "http://www.roblox.com/PlaceItem.aspx?id=#ID"; + + private final int placeId; + private String placeName; + private URI placeUri = null; + + private String creator; + private int creatorId; + + private String thumbnail; + + private boolean isPersonalServer; + + private void getPlaceInformation() throws RobloxPlaceException { + String url = PLACE_URL.replaceAll("#ID", Integer.toString(placeId)); + try { + placeUri = new URL(url).toURI(); + } catch (MalformedURLException e1) { + } catch (URISyntaxException e1) { + } + String response = HttpService.get(url, true); + if (response.isEmpty()) { + throw new RobloxPlaceException("Failed to connect to ROBLOX", placeId, true); + } + LuaScript parseResponse = new LuaScript("parse_place_response.lua"); + LuaValue luaResponse = parseResponse.execute(response); + if (luaResponse == LuaValue.FALSE) { + throw new RobloxPlaceException(placeId); + } else { + try { + placeName = URLDecoder.decode(luaResponse.get("Name").tojstring(), "ASCII"); + } catch (UnsupportedEncodingException e) { + placeName = luaResponse.get("Name").tojstring(); + } + try { + thumbnail = URLDecoder.decode(luaResponse.get("Thumbnail").tojstring(), "UTF-8"); + } catch(UnsupportedEncodingException e) { + thumbnail = luaResponse.get("Thumbnail").tojstring(); + } + try { + creator = URLDecoder.decode(luaResponse.get("Creator").tojstring(), "UTF-8"); + } catch(UnsupportedEncodingException e) { + creator = luaResponse.get("Creator").tojstring(); + } + creatorId = luaResponse.get("CreatorID").toint(); + isPersonalServer = luaResponse.get("IsPersonalServer").toboolean(); + } + } + + /** + * Reflect a Roblox place + * @param placeId Place ID representing the place + * @throws RobloxPlaceException + */ + public RobloxPlace(int placeId) throws RobloxPlaceException { + this.placeId = placeId; + getPlaceInformation(); + } + + /** + * Get the place ID + * @return Place ID + */ + public int getPlaceId() { + return placeId; + } + + /** + * Get the place name + * @return Place name + */ + public String getPlaceName() { + return placeName; + } + + /** + * Get the creator ID + * @return Creator ID + */ + public int getCreatorId() { + return creatorId; + } + + /** + * Get the creator name + * @return Creator name + */ + public String getCreator() { + return creator; + } + + /** + * Get the thumbnail URL + * @return Thumbnail URL + */ + public String getThumbnail() { + return thumbnail; + } + + /** + * Whether or not the place is a personal server + * @return if personal server + */ + public boolean isPersonalServer() { + return isPersonalServer; + } + + /** + * Open the place in the browser + */ + public void openInBrowser() { + Browser.browse(placeUri); + } + +} diff --git a/RobloxLauncher/src/sleitnick/roblox/launcher/RobloxPlaceException.java b/RobloxLauncher/src/sleitnick/roblox/launcher/RobloxPlaceException.java new file mode 100644 index 0000000..3f47644 --- /dev/null +++ b/RobloxLauncher/src/sleitnick/roblox/launcher/RobloxPlaceException.java @@ -0,0 +1,48 @@ +package sleitnick.roblox.launcher; + + + +public class RobloxPlaceException extends Exception { + + private static final long serialVersionUID = 1L; + + private final String msg; + private final int id; + private final boolean failedToConnect; + + public RobloxPlaceException() { + this("Invalid ROBLOX place", -1, false); + } + + public RobloxPlaceException(String msg) { + this(msg, -1, false); + } + + public RobloxPlaceException(int id) { + this("The given ID(" + id + ") is not a valid ROBLOX place", id, false); + } + + public RobloxPlaceException(String msg, int id) { + this(msg, id, false); + } + + public RobloxPlaceException(String msg, int id, boolean failedToConnect) { + this.msg = msg; + this.id = id; + this.failedToConnect = failedToConnect; + } + + @Override + public String getMessage() { + return msg; + } + + public int getID() { + return id; + } + + public boolean getFailedToConnect() { + return failedToConnect; + } + +} diff --git a/RobloxLauncher/src/sleitnick/roblox/launcher/RobloxVersionException.java b/RobloxLauncher/src/sleitnick/roblox/launcher/RobloxVersionException.java new file mode 100644 index 0000000..6feaf7b --- /dev/null +++ b/RobloxLauncher/src/sleitnick/roblox/launcher/RobloxVersionException.java @@ -0,0 +1,26 @@ +package sleitnick.roblox.launcher; + + + +public class RobloxVersionException extends Exception { + + private static final long serialVersionUID = 1L; + + private static final String DEFAULT_MSG = "Current ROBLOX version not installed"; + + private final String msg; + + public RobloxVersionException() { + msg = DEFAULT_MSG; + } + + public RobloxVersionException(String msg) { + this.msg = msg; + } + + @Override + public String getMessage() { + return msg; + } + +} diff --git a/RobloxLauncher/src/sleitnick/roblox/launcher/icon.png b/RobloxLauncher/src/sleitnick/roblox/launcher/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..7b6067637255169aa9b6e003306adb76a783b471 GIT binary patch literal 2466 zcmWlbdpuKp9LLYx8o7)-?1jp-N7A0!B+slNa~(<6XoSZ-_dAKAF?W+hx!;O1A%qZe zr^$FpOY3o4T6=^vw-TPy>-GDc?;pR*Ip_0xe?I4=Ub<)|C7~n%0Du(H+?WJb)!!W| z242IWqu0SA9&BzO1^@>S{q7K;pa}kZhPye*3IL-21c2KK0PtfUtb727Km)*kE&zbb z0|3RK?0*JK!SxzMV?%P(hoT3T{>tn>lJ?JS&CCaHD|I3DAAOOvuranbMJYkE-k(iV zH7ry;__qlJVoEI&i&uk=S3w(3j0d(aGn_mW%ODcRoRH=nXooAQ2|5jiJ$IGOY-%5P zrsf!vkjW}D^Do;|h%?ui1nEj|*nBtnTyy4P?0f3{3PjASY8_eqJ>R_ZC z1bDj?@z(b&JPE>SDQ9RB%3<;*R2DCx%4e?V7+g|KE_H5UAf3amb2>KyKX(%bbnK8g zEw(HHDH~}OJQjBbhx-|>Q)tr4G3j(RYvqW#OXgn?YeXH(wV;yHqVUotHZbXA1XByo zGU{|5`u<((^XJclc6N4q3)nGT3;w1s1RO!i-Pm2{PuBYu=#1)ag^hvpOUzVv0YK%;Fj8mky1NjfewFx`t`dFFrB*Kf;^TzHMNjmg zDp5|Oa(FTH{f7^|?sxPyo88Xn>HW+4J(!W1>E`97{=B<;zkqk6-Vy}x-pD6wZ7ZY4 zlhg_g?`8*KQ;-KJ;#q()ph|nSx2OMG4!Y@4rKC$5G!HHDQdY7HI)zS`@-9d+R%`fz zy-2%Jvb7tIJIpKU)3&-~G2z=h*B)r_Lx>81+p6E|86Ss{s^zmskSJ#F#KeRV1d15u z3AVSncQAT-bhm~SKHtYfEB|dzPmfP(Sgg7dy;p#L&It$}L(sm&a0I;}DtN)@8488+ zYIqo`b{DFZFXt6s^UGkEL{UI-x)?qsHR7jXY7DcIQ+fB2!MR3oI`SDNf6ZU5P45Zf-v7*cK|vU@UZQ%_R5~?0(Z46p{q^ zH+%}zK?g3ik4JRIP4i0QGQpF=W+pUUV}T}k$XQ;fZJi;sauOK~v{lor%!-(6M)`#I z-1kK$=>EAP?#jDSe~u1t{=R28$Vl;Qt*D=$--~d*9Qc?hCdJXwSVO*7Ip`&|bv9PH zC4l=n_vDi)-`#A_jGoo4KD4B^k`#?lzW4E!?g8L^OMp2crICvTw;qo;41$Ky`6iS| zfPlWNwLAFF%{5VJnQq@@ez+2kRceNY_mA8=jsbCZV$WlxX|N}DHJ~mG#%5=vlOluB z+Y$gpSdbo1wgtk)w5<|6?Nw>FNjTM^X@7+_N9jy%8Ci4wp0z$dPVvsr+Ut|`s<{@f zfq~LtVPU(!%5&mjTHiihcQE*{tV4sH%=WamobvsnplXAe8K$2_%SO6}hRXHz^?{@l z8Yn6NSzh#X_b;u+X%yHl7UM)Gwdb*8w@u%-NP*m%BjbIWB{(e)kc43ai%Jq5lVpwr z(Loa9>z0IzPd{KH?v0fF8|WSsBx7l5DQs(aVxTRIht}2oP5rgfTM9X(yee@56pDZm zT)e%ZIiwtmN@2oqvRvhJQZ;!dKwGISXLG17W-8djLuAB5u9_^-8Z>L#Krybh>yU8^ z36TYbBtY?7AHz}x+`L;k!A^=aSO%S5PO2_*sNKsaIXniVv?XAlEqEzlFd7|CC4&rl zHKh{D0bARh!K<|jo12@@+S}8@arD5}^qcx|rJGyr+>IqR#=t;^+4!uXfjT{HkCYRC z`t&Khy>35;6m5JaUlK`V=oG#wn_Z1-f6!bMCZBHdw7#DEuJ-B^vL+UXBQ#ALSCfS* z zEQ8^8>(=45D3v5vRfY6&&>CRkYbc~|uTNU9O_&{Z_3;r0o&Uw^JvcKqb|wfuC{r`# zdlweE(>2iF`1DXgRcH6JXIWArLhnC*?BCqfab$~D%GWIsY;w9jc5N@DZ+~Z=o+vyX z^ALx4WN-}jMu|D*- zx0kJ5y}ZPdT+5v6K_$wj{d*fxpzjkBgvm8ial+fjZXaU_L=gQ|IWz0{pe-tJ9eFvz zX^WkI;dArI2=OeKd@TXs#~Jh^n5Q7L1n93=1Ak5uikV{i@Y~KVh+RxfM>Ck-G3f>?st^u-@BD72_ds+jPOv*C|CXm-zny>Q#za literal 0 HcmV?d00001 diff --git a/RobloxLauncher/src/sleitnick/roblox/launcher/logo.png b/RobloxLauncher/src/sleitnick/roblox/launcher/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..b8804d05d6baf47d8938f7b73f3de0ffd531f6ab GIT binary patch literal 7975 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 literal 0 HcmV?d00001 diff --git a/RobloxLauncher/src/sleitnick/roblox/launcher/parse_place_response.lua b/RobloxLauncher/src/sleitnick/roblox/launcher/parse_place_response.lua new file mode 100644 index 0000000..94f96ef --- /dev/null +++ b/RobloxLauncher/src/sleitnick/roblox/launcher/parse_place_response.lua @@ -0,0 +1,42 @@ +-- Parse Place Response +-- Stephen Leitnick +-- October 19, 2014 + +-- Is given the global variable 'httpResponse' which is a string + + + +-- Get PlaceID from the Play button (which assumes non-place assets will NOT have the button): +local placeId = ( + isPersonalServer + and + httpResponse:match([[class="VisitButton VisitButtonPersonalServer" placeid="(.-)">]]) + or + httpResponse:match([[class="VisitButton VisitButtonPlay" placeid="(.-)">]]) +) + +-- If response shows that the ID given isn't a ROBLOX place: +if (not placeId) then + return false +end + +-- Parse info: +local placeName = httpResponse:match([[

(.-)

]]) +local placeCreatorId, placeCreatorName = httpResponse:match([[(.-)]]) + +-- Get place thumbnail: +local placeThumbnail = httpResponse:match([[ Date: Wed, 23 Aug 2017 09:55:31 +0800 Subject: [PATCH 2/6] Create .classpath --- RobloxLauncher/.classpath | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 RobloxLauncher/.classpath diff --git a/RobloxLauncher/.classpath b/RobloxLauncher/.classpath new file mode 100644 index 0000000..c24d1b4 --- /dev/null +++ b/RobloxLauncher/.classpath @@ -0,0 +1,7 @@ + + + + + + + From 3ba9abd1c5527bba4b932cc3ef02f3d88017a79d Mon Sep 17 00:00:00 2001 From: Samuel Rapana Betio Date: Wed, 23 Aug 2017 09:56:02 +0800 Subject: [PATCH 3/6] Create .gitignore --- RobloxLauncher/.gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 RobloxLauncher/.gitignore diff --git a/RobloxLauncher/.gitignore b/RobloxLauncher/.gitignore new file mode 100644 index 0000000..ae3c172 --- /dev/null +++ b/RobloxLauncher/.gitignore @@ -0,0 +1 @@ +/bin/ From e54d1134705d084bf270a94bcccd50012fd79b92 Mon Sep 17 00:00:00 2001 From: Samuel Rapana Betio Date: Wed, 23 Aug 2017 09:56:35 +0800 Subject: [PATCH 4/6] Create .project --- RobloxLauncher/.project | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 RobloxLauncher/.project diff --git a/RobloxLauncher/.project b/RobloxLauncher/.project new file mode 100644 index 0000000..3e06a36 --- /dev/null +++ b/RobloxLauncher/.project @@ -0,0 +1,17 @@ + + + RobloxLauncher + + + + + + org.eclipse.jdt.core.javabuilder + + + + + + org.eclipse.jdt.core.javanature + + From e55638f534f97f7a8b0b35415881b23df4dd2144 Mon Sep 17 00:00:00 2001 From: Samuel Rapana Betio Date: Wed, 23 Aug 2017 09:56:55 +0800 Subject: [PATCH 5/6] Add files via upload --- RobloxLauncher/settings/org.eclipse.jdt.core.prefs | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 RobloxLauncher/settings/org.eclipse.jdt.core.prefs diff --git a/RobloxLauncher/settings/org.eclipse.jdt.core.prefs b/RobloxLauncher/settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..3a21537 --- /dev/null +++ b/RobloxLauncher/settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,11 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 From 429c330d1cb6695272a4c4c5f4d621ce872c908f Mon Sep 17 00:00:00 2001 From: Samuel Rapana Betio Date: Wed, 23 Aug 2017 09:57:28 +0800 Subject: [PATCH 6/6] Rename RobloxLauncher/settings/org.eclipse.jdt.core.prefs to RobloxLauncher/.settings/org.eclipse.jdt.core.prefs --- RobloxLauncher/{settings => .settings}/org.eclipse.jdt.core.prefs | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename RobloxLauncher/{settings => .settings}/org.eclipse.jdt.core.prefs (100%) diff --git a/RobloxLauncher/settings/org.eclipse.jdt.core.prefs b/RobloxLauncher/.settings/org.eclipse.jdt.core.prefs similarity index 100% rename from RobloxLauncher/settings/org.eclipse.jdt.core.prefs rename to RobloxLauncher/.settings/org.eclipse.jdt.core.prefs