[Easy-TuT] Making installer for Big Resources

Discussion in 'Resources' started by ArsenArsen, Jul 7, 2014.

Thread Status:
Not open for further replies.
  1. Offline

    ArsenArsen

    You have plugin witch have resources like zip files, witch plugin cant make itself? If yes, this is tutorial for you!

    For example, i am making plugin witch has item witch is placing schema. Schema needs to be in plugin directory. You can make downloader!

    ---You need few libraries and one integration for Eclipse.---
    Eclipse WindowBuilder: http://www.eclipse.org/windowbuilder/download.php
    SWT (Standard Widget Toolkit): https://www.eclipse.org/swt/
    Apache FileUtils Library: http://commons.apache.org/proper/commons-io/download_io.cgi
    Zip4J: http://www.lingala.net/zip4j/download.php

    First of all, you need to install WindowBuilder. Go to link above and select your Eclipse version. On redirected page you have instructions how to to install.

    Second, Download SWT and import it to your Eclipse.

    --- Classes ---

    NOTE: When you are typing the path, insteand of \ place \\, becouse \ is ESCAPE CHARACTER! (More about escape characters can be founded here (Section is JavaScript becouse JS have those characters))

    Make new WindowBuilder project ( File ---> New... ---> Other ---> WindowBuilder ---> SWT Designer ---> SWT/JFace Java Project)

    Make new package and in it make new SWT Aplication Window (Button next to New Project ---> SWT ---> Aplication Window) NOTE: Make sure you selected protected createMethod().

    It should look like:
    [​IMG]

    Click on design tab, Click on the window and select text. Make button and textbox.

    Button text can be anything (maybe Install {PLUGIN_NAME})

    Next, make textbox and in style select Lines then MULTIPLE.

    Add folowing code to your source, at the end.

    Code:java
    1. String currentDir = System.getProperty("user.dir");
    2. textbox.setText("Current Working Directory is: " + currentDir + "\r\nInstaller has started...\r\nWaiting for command...");


    Replace textbox with variable text from desing tab.

    Add apache library from above to build path

    Then, lets make event handler for button. Right click button, then Add Event Handler ---> mouse ---> MouseDown

    --- String Writer for Errors ---
    Add these lines under public class ...​
    Code:
    private StringWriter sw = new StringWriter();
    private PrintWriter pw = new PrintWriter(sw);
    ---Adding folowing code to newly created EventHandler---
    Code:java
    1. DirectoryDialog dialog = new DirectoryDialog(shlTentmodInstaller, SWT.OPEN);
    2. dialog.setFilterPath("c:\\");
    3. dialog.setText("Select your server folder");
    4. String result = dialog.open();
    5. boolean success = (new File(result + "\\plugins\\" + "PLUGIN_NAME")).mkdirs();
    6. String textboxtxt = textbox.getText();
    7. if (!success) {
    8. textbox.setText(textboxtxt + "\r\nMaking folder FAILED! Did folder exist???");
    9. } else {
    10. textbox.setText(textboxtxt + "\r\nMaking folder SUCESS\r\nDownloading files!");
    11. try {
    12. URL url = new URL(url_to_resource);
    13. File destination = new File(result + "plugins\\PLUGIN_NAME\\RESOURCE.NAME");
    14. FileUtils.copyURLToFile(url, destination);
    15. } catch (IOException e1) {
    16. e1.printStackTrace(pw);
    17. String err = sw.toString();
    18. textbox.setText(textbox.getText() + "\r\nINTERNAL ERROR\r\nVIEW STACK TRACE:\r\n" + err);
    19. }
    20. try {
    21. URL urlj = new URL(jar_url);
    22. File destinationjar = new File(result + "plugins\\JAR_NAME.jar");
    23. FileUtils.copyURLToFile(urlj, destinationjar);
    24. } catch (IOException e1) {
    25. e1.printStackTrace(pw);
    26. String err = sw.toString();
    27. textbox.setText(textbox.getText() + "\r\nINTERNAL ERROR\r\nVIEW STACK TRACE:\r\n" + err);
    28. }
    29. }
    30. }

    Replace textbox to your textbox variable, as i said before

    --- Adding more resources ---
    To add more resources add this to your mouseDown handler:​
    Code:java
    1. try {
    2. URL newurl = new URL(res_url);
    3. File newdestinationfile = new File(result + "plugins\\PLUGIN_NAME\\RES.NAME");
    4. FileUtils.copyURLToFile(newurl, newdestinationfile);
    5. } catch (IOException e1) {
    6. e1.printStackTrace(pw);
    7. String err = sw.toString();
    8. textbox.setText(textbox.getText() + "\r\nINTERNAL ERROR\r\nVIEW STACK TRACE:\r\n" + err);
    9. }
    10. }

    Then, add this deleter:
    Code:java
    1. try{
    2.  
    3. File file = new File(result + "\\plugins\\PL_NAME\\ZIP_NAME.zip");
    4.  
    5. if(file.delete()){
    6. txtInstallerHasStarted.setText(txtInstallerHasStarted.getText() + "/r/nSUCCESS DELETION");
    7. }else{
    8. txtInstallerHasStarted.setText(txtInstallerHasStarted.getText() + "/r/nINTERNAL ERROR\r\nDELETE FILE MANUALLY");
    9. }
    10.  
    11. }catch(Exception e){
    12.  
    13. e.printStackTrace();
    14.  
    15. }


    --- You will need folowing imports to make this work: ---
    Code:java
    1. import java.io.File;
    2. import java.io.IOException;
    3. import java.io.PrintWriter;
    4. import java.io.StringWriter;
    5. import java.net.URL;
    6. import org.apache.commons.io.FileUtils;
    7. import org.eclipse.swt.SWT;
    8. import org.eclipse.swt.widgets.DirectoryDialog;
    9. import org.eclipse.swt.widgets.Display;
    10. import org.eclipse.swt.widgets.Shell;
    11. import org.eclipse.swt.widgets.Button;
    12. import org.eclipse.swt.widgets.Text;
    13. import org.eclipse.swt.events.MouseAdapter;
    14. import org.eclipse.swt.events.MouseEvent;


    Replace ALL things to your wish.

    Optionaly, you can add exit button:

    Make new button, new event handler for mousedown and place
    Code:java
    1. shlell.close()


    If your shell variable is different, edit my code.

    --- Big Resources, Zip files! ---

    If your resource is .zip file you can use Zip4J library, download it and add to build path.
    Then, add:
    Code:java
    1. try {
    2. ZipFile zipFile = new ZipFile("zip_name.zip");
    3. if (zipFile.isEncrypted()) {
    4. zipFile.setPassword("pass_if_needed");
    5. }
    6. zipFile.extractAll(result + "\\plugins\\Plugin_Name");
    7. } catch (ZipException ze) {
    8. e1.printStackTrace(pw);
    9. String zeps = sw.toString();
    10. txtInstallerHasStarted.setText(txtInstallerHasStarted.getText() + "\r\nINTERNAL ERROR\r\nWIEW STACK TRACE:\r\n" + zeps);
    11. }

    Then, we delete installed file, add
    Code:java
    1. try{
    2.  
    3. File file = new File(result + "\\plugins\\Pl_Folder\\res.name");
    4.  
    5. if(file.delete()){
    6. txtInstallerHasStarted.setText(txtInstallerHasStarted.getText() + "\r\n" + file.getName() + " is deleted!");
    7. }else{
    8. txtInstallerHasStarted.setText(txtInstallerHasStarted.getText() + "\r\nDelete operation is failed.");
    9. }
    10.  
    11. }catch(Exception ee){
    12. String es = ee.toString();
    13. txtInstallerHasStarted.setText(txtInstallerHasStarted.getText() + "/r/nINTERNAL ERROR\r\nVIEW STACK TRACKE:\r\n" + es);
    14. }


    ---Another maybe-usefull thing, settings!---

    Repeat making process above and make 2 textboxes and three buttons in new class.

    Then, extend main class with new class.

    Use following code and edit it to your wish:

    Code:java
    1.  
    2. import org.eclipse.swt.widgets.Display;
    3. import org.eclipse.swt.widgets.Shell;
    4. import org.eclipse.swt.widgets.Button;
    5. import org.eclipse.swt.SWT;
    6. import org.eclipse.swt.widgets.Text;
    7. import org.eclipse.swt.events.MouseAdapter;
    8. import org.eclipse.swt.events.MouseEvent;
    9.  
    10. public class Adv_Settings {
    11. protected Shell shell = new Shell();
    12. private Text text;
    13. public static String urls = new String("url");
    14. public static String jar_url = new String("jarurl");
    15. private Text text_1;
    16.  
    17. /**
    18. * Launch the application.
    19. * @param args
    20. */
    21. public static void main(String[] args) {
    22. try {
    23. Adv_Settings window = new Adv_Settings();
    24. window.open();
    25. } catch (Exception e) {
    26. e.printStackTrace();
    27. }
    28. }
    29.  
    30. /**
    31. * Open the window.
    32. */
    33. public void open() {
    34. Display display = Display.getDefault();
    35. shell.setSize(276, 134);
    36. shell.setText("Advanced Settings - {PLUGIN_NAME} Installer");
    37.  
    38.  
    39. Button btnApply = new Button(shell, SWT.NONE);
    40. btnApply.addMouseListener(new MouseAdapter() {
    41. @Override
    42. public void mouseDown(MouseEvent e) {
    43. if(text.getText().equals("")){
    44. urls = "resurl";
    45. } else urls = text.getText();
    46. if(text_1.getText().equals("")){
    47. jar_url = "jarurl";
    48. } else jar_url = text_1.getText();
    49. }
    50. });
    51. btnApply.setBounds(91, 64, 75, 25);
    52. btnApply.setText("Apply");
    53.  
    54. Button btnOk = new Button(shell, SWT.NONE);
    55. btnOk.addMouseListener(new MouseAdapter() {
    56. @Override
    57. public void mouseDown(MouseEvent e) {
    58. if(text.getText().equals("")){
    59. urls = "default/path/to/resource";
    60. } else urls = text.getText();
    61. if(text_1.getText().equals("")){
    62. jar_url = "/default/path/to/jar/dev/bukkit/org";
    63. } else jar_url = text_1.getText();
    64. shell.close();
    65. }
    66.  
    67.  
    68. });
    69. btnOk.setBounds(10, 64, 75, 25);
    70. btnOk.setText("Ok");
    71.  
    72. Button btnCancel = new Button(shell, SWT.NONE);
    73. btnCancel.addMouseListener(new MouseAdapter() {
    74. @Override
    75. public void mouseDown(MouseEvent e) {
    76. shell.close();
    77. }
    78. });
    79. btnCancel.setBounds(172, 64, 75, 25);
    80. btnCancel.setText("Cancel");
    81.  
    82. text = new Text(shell, SWT.BORDER);
    83. text.setBounds(10, 10, 237, 21);
    84. text.setMessage("Insert your specific URL");
    85.  
    86. text_1 = new Text(shell, SWT.BORDER);
    87. text_1.setBounds(10, 37, 237, 21);
    88. text_1.setMessage("Insert your specific URL for JAR file");
    89.  
    90. shell.open();
    91. shell.layout();
    92. while (!shell.isDisposed()) {
    93. if (!display.readAndDispatch()) {
    94. display.sleep();
    95. }
    96. }
    97. }
    98. }
    99.  

    As is said LOTS times before make it to be compatibile to you.

    Main class needs to be same, just extend and replace urls and others with variables.

    In Main class add one button, Settings, and button mouseDown event should be:
    Code:java
    1. Class_Name config = new Class_Name();
    2. config.open();


    Thats all for today, leave your plugins to comments and feel free to ask!

    --- Exporting your installer ---
    To export your installer, make manifest file( more on this FAQ ), right click project in Package Manager and then Export.
    Press Executable JAR ---> Enter name and other stuff then Ok. Is it complicated, Leave comments below and i will explain!
    ---If you have updater---
    There is one more importaint thing, if you have Gravitys updater (HIGHLY RECOMENDED!) you must do {PLUGIN_NAME} v{VERSION}-INSTALLER

    Code:
      public boolean shouldUpdate(String localVersion, String remoteVersion) {
            if (remoteVersion.contains("INSTALLER") return false;
            return !localVersion.equalsIgnoreCase(remoteVersion);
        }
    Thanks Gravity for this updater note!
    --- You're Done! ---
    Below you have picture of done GUI! CaptureGUI.PNG
     

    Attached Files:

  2. Offline

    Bammerbom

    ArsenArsen
    Nice work!
    But I am not sure if bukkit will accept Installer files.
     
  3. Offline

    ljjuuuyyy

    It's a nice idea, that can be transferred to other projects pretty easily, but I don't see much of an advantage of using this over uploading a zip file to BukkitDev, especially since schematic files are rather small, and most server owners are used to drag/dropping everything into their plugins folder as it is.
     
  4. Offline

    ArsenArsen

    This is automatization and i dont bellive they have much time, just Open ---> Select ---> Done!
    I asked Gravity about updating, he had no reaction. I dont know neither

    Bammerbom i think they do. Im not sure.

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 9, 2016
  5. Offline

    turt2live

    Personally I just compile the resources into the JAR file and leverage the Bukkit API to get them out for me.
     
  6. Offline

    ArsenArsen

    What?
     
  7. Offline

    turt2live

    If the files are already in the JAR file, then you don't need to download them. Generally anything that is being downloaded from the internet via the plugin can be added to the JAR itself. Once it's in the JAR file you can use a combination of the plugin's directory and various (1, 2) utility methods to save the file to the data folder. Overall it's a cleaner process as it's as simple as "if not exists, save" during the plugin initialization. This way you avoid trying to figure out whether or not what you are doing is against the rules of DBO/Bukkit and avoid the potential user error in setting up the plugin. Or, as previously mentioned, a ZIP file works just as well.

    edit: Bonus points if your plugin doesn't save the file if it doesn't have to.
     
  8. Offline

    ArsenArsen

    turt2live
    I thinked about making something usefull, thanks for breaking it. :(
     
  9. Offline

    turt2live

    I never said it was useless. What you made is one way to do possibly some sort of package management over what I've mentioned which is a "install everything" method. A package management tool could be used for a plugin which uses entire world files (or something like that). Those files are generally large and you wouldn't want them in the plugin JAR itself, so you would likely have them elsewhere and people could selectively download and "install" these maps for the plugin to use. Another scenario would be plugins for plugins. Basically any optional dependency could be used in a package manager system, which you have a pretty good starting point for as is.
     
    ArsenArsen likes this.
  10. Offline

    ArsenArsen

    Ooo didnt know that, i didnt saw another reason, time for update! :D
     
  11. Offline

    turt2live

    :D I look forward to seeing what you come up with.
     
  12. Offline

    ArsenArsen

    Thanks!
     
  13. Offline

    ArsenArsen

    I am done ;D
     
  14. Offline

    turt2live

    Looks good :)
     
    ArsenArsen likes this.
  15. Offline

    CeramicTitan

  16. Offline

    ArsenArsen

    Of course. Putted it under --- You're Done! --- section
     
    CeramicTitan likes this.
  17. Offline

    ArsenArsen

    CeramicTitan is this policy-complaint, some potentional users are asking
     
  18. Offline

    mbaxter ʇıʞʞnq ɐ sɐɥ ı

    ArsenArsen Includes additional libraries which are not required for plugin functioning, and downloads external unreviewed files? That's a rejection.
     
  19. Just saying, it's spelt "which" not "witch"...
     
    ArsenArsen likes this.
  20. Offline

    ArsenArsen

    So much work, so much time spended, all dropped into water :(, I realised im worth as [gravel]
     
  21. In UHC, you and chickens are worth a lot.
     
    LordVakar likes this.
Thread Status:
Not open for further replies.

Share This Page