├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── license-definitions.xml ├── pom.xml └── src └── main ├── java └── com │ └── github │ └── pemapmodder │ └── pocketminegui │ ├── PocketMineGUI.java │ ├── gui │ ├── server │ │ ├── ConsolePanel.java │ │ ├── InternalMessage.java │ │ ├── LineReader.java │ │ ├── ServerLifetime.java │ │ └── ServerMainActivity.java │ └── startup │ │ ├── ChooseServerActivity.java │ │ ├── config │ │ ├── ServerOptionsActivity.java │ │ └── adaptor │ │ │ ├── CheckBoxOptionAdaptor.java │ │ │ ├── NumberFieldAdaptor.java │ │ │ └── OptionAdaptor.java │ │ └── installer │ │ ├── FetchVersionsThread.java │ │ ├── InstallPHPThread.java │ │ ├── InstallServerActivity.java │ │ ├── Release.java │ │ ├── ReleaseType.java │ │ └── cards │ │ ├── ChooseLocationCard.java │ │ ├── ChooseVersionCard.java │ │ ├── DownloadProgressCard.java │ │ ├── PhpInstallerCard.java │ │ └── ServerSetupCard.java │ ├── lib │ ├── Activity.java │ ├── JNumberFilter.java │ └── card │ │ ├── Card.java │ │ └── CardActivity.java │ └── utils │ ├── AsyncTask.java │ ├── GetUrlThread.java │ ├── NonBlockingANSIReader.java │ ├── NonBlockingBufferedReader.java │ ├── Ring.java │ ├── TerminalCode.java │ └── Utils.java └── resources ├── plugins └── adaptor.php └── pocketmine.yml /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Java template 3 | *.class 4 | 5 | # Mobile Tools for Java (J2ME) 6 | .mtj.tmp/ 7 | 8 | # Package Files # 9 | *.jar 10 | *.war 11 | *.ear 12 | 13 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 14 | hs_err_pid* 15 | ### JetBrains template 16 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio 17 | 18 | *.iml 19 | 20 | ## Directory-based project format: 21 | .idea/ 22 | # if you remove the above rule, at least ignore the following: 23 | 24 | # User-specific stuff: 25 | # .idea/workspace.xml 26 | # .idea/tasks.xml 27 | # .idea/dictionaries 28 | 29 | # Sensitive or high-churn files: 30 | # .idea/dataSources.ids 31 | # .idea/dataSources.xml 32 | # .idea/sqlDataSources.xml 33 | # .idea/dynamic.xml 34 | # .idea/uiDesigner.xml 35 | 36 | # Gradle: 37 | # .idea/gradle.xml 38 | # .idea/libraries 39 | 40 | # Mongo Explorer plugin: 41 | # .idea/mongoSettings.xml 42 | 43 | ## File-based project format: 44 | *.ipr 45 | *.iws 46 | 47 | ## Plugin-specific files: 48 | 49 | # IntelliJ 50 | /out/ 51 | 52 | # mpeltonen/sbt-idea plugin 53 | .idea_modules/ 54 | 55 | # JIRA plugin 56 | atlassian-ide-plugin.xml 57 | 58 | # Crashlytics plugin (for Android Studio and IntelliJ) 59 | com_crashlytics_export_strings.xml 60 | crashlytics.properties 61 | crashlytics-build.properties 62 | ### NetBeans template 63 | nbproject/private/ 64 | build/ 65 | nbbuild/ 66 | dist/ 67 | nbdist/ 68 | nbactions.xml 69 | nb-configuration.xml 70 | .nb-gradle/ 71 | ### Maven template 72 | target/ 73 | pom.xml.tag 74 | pom.xml.releaseBackup 75 | pom.xml.versionsBackup 76 | pom.xml.next 77 | release.properties 78 | dependency-reduced-pom.xml 79 | buildNumber.properties 80 | .mvn/timing.properties 81 | ### Eclipse template 82 | *.pydevproject 83 | .metadata 84 | .gradle 85 | test/bin/ 86 | tmp/ 87 | *.tmp 88 | *.bak 89 | *.swp 90 | *~.nib 91 | local.properties 92 | .settings/ 93 | .loadpath 94 | 95 | # Eclipse Core 96 | .project 97 | 98 | # External tool builders 99 | .externalToolBuilders/ 100 | 101 | # Locally stored "Eclipse launch configurations" 102 | *.launch 103 | 104 | # CDT-specific 105 | .cproject 106 | 107 | # JDT-specific (Eclipse Java Development Tools) 108 | .classpath 109 | 110 | # Java annotation processor (APT) 111 | .factorypath 112 | 113 | # PDT-specific 114 | .buildpath 115 | 116 | # sbteclipse plugin 117 | .target 118 | 119 | # TeXlipse plugin 120 | .texlipse 121 | 122 | # Custom 123 | PocketMine-MP/ 124 | test/ 125 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | sudo: false 3 | install: 4 | - (mvn license:check package || echo) > /dev/null # pre-run the script to install plugins 5 | - rm -r target # clean directory 6 | script: mvn license:check package 7 | jdk: [oraclejdk8] 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | 167 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PocketMine-GUI [![on Travis-CI](https://travis-ci.org/PEMapModder/PocketMine-GUI.svg)](https://travis-ci.org/PEMapModder/PocketMine-GUI) 2 | 3 | [![Join the chat at https://gitter.im/PEMapModder/PocketMine-GUI](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/PEMapModder/PocketMine-GUI?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 4 | Java Swing-based PocketMine-MP GUI 5 | 6 | Compiling/Running 7 | === 8 | * Install maven 9 | * Run these maven goals: 10 | * `package` - compiles the project and packs classes into a jar 11 | * `exec:java` - executes the jar 12 | 13 | For debugging, running `mvn package exec:java` every test is recommended. 14 | -------------------------------------------------------------------------------- /license-definitions.xml: -------------------------------------------------------------------------------- 1 | 2 | 20 | 21 | 22 | 23 | /* 24 | * 25 | */ 26 | (\s|\t)*/\*.*$ 27 | .*\*/(\s|\t)*$ 28 | false 29 | true 30 | false 31 | 32 | 33 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 20 | 21 | 24 | 4.0.0 25 | 26 | com.github.pemapmodder 27 | PocketMine-GUI 28 | 1.0-SNAPSHOT 29 | 30 | 31 | 32 | 33 | org.projectlombok 34 | lombok 35 | 1.16.6 36 | provided 37 | 38 | 39 | 40 | org.apache.commons 41 | commons-lang3 42 | 3.3.2 43 | 44 | 45 | 46 | com.googlecode.json-simple 47 | json-simple 48 | 1.1 49 | 50 | 51 | 52 | commons-io 53 | commons-io 54 | 2.4 55 | 56 | 57 | 58 | org.apache.commons 59 | commons-compress 60 | 1.10 61 | 62 | 63 | 64 | commons-collections 65 | commons-collections 66 | 3.2.2 67 | 68 | 69 | 70 | 71 | org.json 72 | json 73 | 20150729 74 | 75 | 76 | 77 | org.yaml 78 | snakeyaml 79 | 1.16 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | org.apache.maven.plugins 88 | maven-compiler-plugin 89 | 3.3 90 | 91 | 1.8 92 | 1.8 93 | UTF-8 94 | 95 | 96 | 97 | 98 | org.apache.maven.plugins 99 | maven-javadoc-plugin 100 | 2.10.3 101 | 102 | UTF-8 103 | 104 | 105 | 106 | 107 | com.mycila 108 | license-maven-plugin 109 | 2.11 110 | 111 |
com/mycila/maven/plugin/license/templates/LGPL-3.txt
112 | 113 | 114 | license-definitions.xml 115 | 116 | 117 | 118 | **/README 119 | **/LICENSE 120 | src/test/resources/** 121 | src/main/resources/** 122 | PocketMine-MP/** 123 | test/** 124 | 125 |
126 | 127 | 128 | package 129 | 130 | check 131 | 132 | 133 | 134 |
135 | 136 | 137 | org.apache.maven.plugins 138 | maven-shade-plugin 139 | 2.3 140 | 141 | 142 | 143 | package 144 | 145 | shade 146 | 147 | 148 | 149 | 150 | 152 | com.github.pemapmodder.pocketminegui.PocketMineGUI 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | org.codehaus.mojo 162 | exec-maven-plugin 163 | 1.2.1 164 | 165 | com.github.pemapmodder.pocketminegui.PocketMineGUI 166 | 167 | 168 | 169 | 170 | java 171 | 172 | 173 | 174 | 175 |
176 |
177 |
178 | -------------------------------------------------------------------------------- /src/main/java/com/github/pemapmodder/pocketminegui/PocketMineGUI.java: -------------------------------------------------------------------------------- 1 | package com.github.pemapmodder.pocketminegui; 2 | 3 | /* 4 | * This file is part of PocketMine-GUI. 5 | * 6 | * PocketMine-GUI is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PocketMine-GUI is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with PocketMine-GUI. If not, see . 18 | */ 19 | 20 | import com.github.pemapmodder.pocketminegui.gui.startup.ChooseServerActivity; 21 | import com.github.pemapmodder.pocketminegui.lib.Activity; 22 | 23 | /** 24 | * Entry class to the program 25 | */ 26 | public class PocketMineGUI{ 27 | public static Activity CURRENT_ROOT_ACTIVITY = null; 28 | 29 | public static void main(String[] args){ 30 | new ChooseServerActivity().init(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/github/pemapmodder/pocketminegui/gui/server/ConsolePanel.java: -------------------------------------------------------------------------------- 1 | package com.github.pemapmodder.pocketminegui.gui.server; 2 | 3 | /* 4 | * This file is part of PocketMine-GUI. 5 | * 6 | * PocketMine-GUI is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PocketMine-GUI is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with PocketMine-GUI. If not, see . 18 | */ 19 | 20 | import com.github.pemapmodder.pocketminegui.utils.NonBlockingANSIReader; 21 | import com.github.pemapmodder.pocketminegui.utils.Ring; 22 | import com.github.pemapmodder.pocketminegui.utils.TerminalCode; 23 | import org.apache.commons.lang3.StringUtils; 24 | 25 | import javax.swing.*; 26 | import javax.swing.text.BadLocationException; 27 | import javax.swing.text.Element; 28 | import javax.swing.text.Style; 29 | import javax.swing.text.html.HTMLDocument; 30 | import java.awt.Color; 31 | import java.awt.Dimension; 32 | import java.awt.GridBagConstraints; 33 | import java.awt.GridBagLayout; 34 | import java.awt.event.KeyAdapter; 35 | import java.awt.event.KeyEvent; 36 | import java.io.IOException; 37 | 38 | public class ConsolePanel extends JPanel{ 39 | private final static int BUFFER_SIZE = 100; 40 | private final ServerMainActivity activity; 41 | private final JLabel title; 42 | private final JEditorPane stdout; 43 | private final HTMLDocument doc; 44 | private final Element para; 45 | private final Ring consoleBuffer = new Ring<>(new String[BUFFER_SIZE]); 46 | 47 | public ConsolePanel(ServerMainActivity activity){ 48 | this.activity = activity; 49 | setLayout(new GridBagLayout()); 50 | setBorder(BorderFactory.createEmptyBorder(20, 10, 20, 10)); 51 | title = new JLabel("PocketMine-MP"); 52 | GridBagConstraints c = new GridBagConstraints(); 53 | c.anchor = GridBagConstraints.CENTER; 54 | c.fill = GridBagConstraints.HORIZONTAL; 55 | c.weighty = 0.0; 56 | add(title, c); 57 | stdout = new JEditorPane(){ 58 | @Override 59 | public boolean getScrollableTracksViewportHeight(){ 60 | return true; 61 | } 62 | 63 | @Override 64 | public boolean getScrollableTracksViewportWidth(){ 65 | return true; 66 | } 67 | }; 68 | stdout.setContentType("text/html"); 69 | stdout.setText("





" + 70 | "

















"); 71 | doc = (HTMLDocument) stdout.getDocument(); 72 | para = doc.getElement("p"); 73 | JScrollPane scrollPane = new JScrollPane(); 74 | stdout.setEditable(false); 75 | // People NEED to see this to feel happy 76 | stdout.setForeground(Color.WHITE); 77 | stdout.setBackground(Color.BLACK); 78 | Style style = doc.getStyleSheet().addStyle(null, null); 79 | doc.setParagraphAttributes(para.getStartOffset(), 1, style, true); 80 | scrollPane.getViewport().add(stdout); 81 | scrollPane.setMinimumSize(new Dimension(200, 200)); 82 | scrollPane.setPreferredSize(new Dimension(500, 400)); 83 | scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); 84 | c.gridy = 1; 85 | c.weightx = 0.9; 86 | c.weighty = 0.0; 87 | c.fill = GridBagConstraints.BOTH; 88 | c.anchor = GridBagConstraints.NORTHWEST; 89 | add(scrollPane, c); 90 | JTextField stdin = new JTextField(); 91 | stdin.addKeyListener(new MyKeyAdapter(stdin, activity)); 92 | c.gridy = 2; 93 | c.weighty = 0.0; 94 | c.fill = GridBagConstraints.HORIZONTAL; 95 | add(stdin, c); 96 | Timer timer = new Timer(50, e -> updateConsole()); 97 | timer.start(); 98 | } 99 | 100 | private void updateConsole(){ 101 | NonBlockingANSIReader reader = activity.getStdoutBuffered(); 102 | if(reader == null){ 103 | return; 104 | } 105 | NonBlockingANSIReader.Entry entry; 106 | while((entry = reader.nextOutput()) != null){ 107 | if(entry.getType() == NonBlockingANSIReader.EntryType.TITLE){ 108 | title.setText(entry.getLine()); 109 | continue; 110 | } 111 | if(entry.getType() == NonBlockingANSIReader.EntryType.PMGUI){ 112 | activity.getLifetime().handlePluginMessage(new InternalMessage(entry.getLine())); 113 | continue; 114 | } 115 | String line = TerminalCode.toHTML(entry.getLine()); 116 | String text = stdout.getText(); 117 | consoleBuffer.add(line); 118 | 119 | try{ 120 | doc.setInnerHTML(para, StringUtils.join(consoleBuffer, "
")); 121 | }catch(BadLocationException | IOException e){ 122 | e.printStackTrace(); 123 | } 124 | 125 | String clean = TerminalCode.clean(entry.getLine()); 126 | activity.getLifetime().handleConsoleOutput(clean); 127 | } 128 | } 129 | 130 | private static class MyKeyAdapter extends KeyAdapter{ 131 | private final JTextField stdin; 132 | private final ServerMainActivity activity; 133 | Ring consoleLog = new Ring<>(new String[50]); 134 | int neg = 0; 135 | String tmpText = ""; 136 | 137 | public MyKeyAdapter(JTextField stdin, ServerMainActivity activity){ 138 | this.stdin = stdin; 139 | this.activity = activity; 140 | } 141 | 142 | @Override 143 | public void keyPressed(KeyEvent e){ 144 | String newText = null; 145 | if(e.getKeyCode() == KeyEvent.VK_ENTER){ 146 | if(activity.getProcess() == null){ 147 | return; 148 | } 149 | try{ 150 | String line = stdin.getText(); 151 | activity.getStdin().write(line.concat(System.lineSeparator()).getBytes()); 152 | newText = ""; 153 | neg = 0; 154 | consoleLog.add(line); 155 | }catch(IOException e1){ 156 | e1.printStackTrace(); 157 | return; 158 | } 159 | }else if(e.getKeyCode() == KeyEvent.VK_UP || e.getKeyChar() == KeyEvent.VK_KP_UP){ 160 | ++neg; 161 | if(neg == 1){ 162 | tmpText = stdin.getText(); 163 | } 164 | try{ 165 | newText = consoleLog.get(consoleLog.getSize() - neg); 166 | }catch(IndexOutOfBoundsException e1){ 167 | --neg; 168 | return; 169 | } 170 | }else if(e.getKeyCode() == KeyEvent.VK_DOWN || e.getKeyCode() == KeyEvent.VK_KP_DOWN){ 171 | if(neg <= 0){ 172 | neg = 0; 173 | return; 174 | } 175 | --neg; 176 | if(neg == 0){ 177 | newText = tmpText; 178 | }else{ 179 | newText = consoleLog.get(consoleLog.getSize() - neg); 180 | } 181 | } 182 | if(newText != null){ 183 | stdin.setText(newText); 184 | } 185 | } 186 | } 187 | } 188 | -------------------------------------------------------------------------------- /src/main/java/com/github/pemapmodder/pocketminegui/gui/server/InternalMessage.java: -------------------------------------------------------------------------------- 1 | package com.github.pemapmodder.pocketminegui.gui.server; 2 | 3 | /* 4 | * This file is part of PocketMine-GUI. 5 | * 6 | * PocketMine-GUI is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PocketMine-GUI is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with PocketMine-GUI. If not, see . 18 | */ 19 | 20 | import lombok.Getter; 21 | import lombok.RequiredArgsConstructor; 22 | import org.json.JSONObject; 23 | 24 | @Getter 25 | public class InternalMessage{ 26 | @RequiredArgsConstructor 27 | @Getter 28 | public enum Type{ 29 | SERVER_STARTED(0), 30 | PLAYER_JOIN(1), 31 | PLAYER_QUIT(2), 32 | PLUGIN_DISABLED(3); 33 | 34 | private final int type; 35 | 36 | public static Type get(int id){ 37 | for(Type type : values()){ 38 | if(type.type == id){ 39 | return type; 40 | } 41 | } 42 | return null; 43 | } 44 | } 45 | 46 | private final Type type; 47 | private final JSONObject data; 48 | 49 | public InternalMessage(String line){ 50 | line = line.substring(8); 51 | int index = line.indexOf(':'); 52 | type = Type.get(Integer.parseInt(line.substring(0, index))); 53 | String json = line.substring(index + 1); 54 | data = new JSONObject(json); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/com/github/pemapmodder/pocketminegui/gui/server/LineReader.java: -------------------------------------------------------------------------------- 1 | package com.github.pemapmodder.pocketminegui.gui.server; 2 | 3 | /* 4 | * This file is part of PocketMine-GUI. 5 | * 6 | * PocketMine-GUI is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PocketMine-GUI is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with PocketMine-GUI. If not, see . 18 | */ 19 | 20 | import lombok.RequiredArgsConstructor; 21 | 22 | @RequiredArgsConstructor 23 | public class LineReader{ 24 | private final String src; 25 | private int pointer = 0; 26 | 27 | public void expect(String string){ 28 | if(!src.substring(pointer, pointer + string.length()).equals(string)){ 29 | throw new RuntimeException("Unexpected console output"); 30 | } 31 | pointer += string.length(); 32 | } 33 | 34 | public void expect(char ch){ 35 | if(src.charAt(pointer) != ch){ 36 | throw new RuntimeException("Unexpected console output"); 37 | } 38 | ++pointer; 39 | } 40 | 41 | public String readBefore(char until){ 42 | int pos = src.indexOf(until, pointer); 43 | String substring = src.substring(pointer, pos); 44 | pointer = pos; 45 | return substring; 46 | } 47 | 48 | public String readThrough(char until){ 49 | int pos = src.indexOf(until, pointer); 50 | String substring = src.substring(pointer, pos); 51 | pointer = pos + 1; 52 | return substring; 53 | } 54 | 55 | public String readUntil(char until){ 56 | int pos = src.indexOf(until, pointer); 57 | String substring = src.substring(pointer, pos + 1); 58 | pointer = pos + 1; 59 | return substring; 60 | } 61 | 62 | public String readRemaining(){ 63 | String substring = src.substring(pointer); 64 | pointer = src.length(); 65 | return substring; 66 | } 67 | 68 | public boolean eof(){ 69 | return pointer >= src.length(); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/com/github/pemapmodder/pocketminegui/gui/server/ServerLifetime.java: -------------------------------------------------------------------------------- 1 | package com.github.pemapmodder.pocketminegui.gui.server; 2 | 3 | /* 4 | * This file is part of PocketMine-GUI. 5 | * 6 | * PocketMine-GUI is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PocketMine-GUI is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with PocketMine-GUI. If not, see . 18 | */ 19 | 20 | import com.github.pemapmodder.pocketminegui.gui.server.ServerMainActivity.ServerState; 21 | import lombok.Getter; 22 | import lombok.RequiredArgsConstructor; 23 | 24 | import javax.swing.JButton; 25 | import java.awt.event.ActionEvent; 26 | import java.io.IOException; 27 | 28 | @RequiredArgsConstructor 29 | public class ServerLifetime{ 30 | @Getter private final ServerMainActivity activity; 31 | @Getter private ServerState state = ServerState.STATE_STOPPED; 32 | 33 | public void nextState(){ 34 | JButton button = activity.getStartStopButton(); 35 | if(state == ServerState.STATE_STOPPED){ 36 | state = ServerState.STATE_STARTING; 37 | button.setText(state.getButtonName()); 38 | button.setEnabled(false); 39 | }else if(state == ServerState.STATE_STARTING){ 40 | state = ServerState.STATE_RUNNING; 41 | button.setText(state.getButtonName()); 42 | button.setEnabled(true); 43 | }else if(state == ServerState.STATE_RUNNING){ 44 | setStateStopping(); 45 | } 46 | } 47 | 48 | public void setStateStopping(){ 49 | state = ServerState.STATE_STOPPING; 50 | JButton button = activity.getStartStopButton(); 51 | button.setText(state.getButtonName()); 52 | button.setEnabled(false); 53 | } 54 | 55 | public void listen(ActionEvent e){ 56 | if(state == ServerState.STATE_STOPPED){ 57 | nextState(); 58 | activity.startServer(); 59 | }else if(state == ServerState.STATE_RUNNING){ 60 | nextState(); 61 | try{ 62 | activity.getStdin().write("stop".concat(System.lineSeparator()).getBytes()); 63 | }catch(IOException e1){ 64 | e1.printStackTrace(); 65 | } 66 | } 67 | } 68 | 69 | public void handleConsoleOutput(String clean){ 70 | LineReader r = new LineReader(clean.trim()); 71 | try{ 72 | r.expect('['); 73 | int hour = Integer.parseInt(r.readThrough(':')); 74 | int minute = Integer.parseInt(r.readThrough(':')); 75 | int second = Integer.parseInt(r.readThrough(']')); 76 | r.readUntil('['); 77 | String thread = r.readThrough('/'); 78 | String type = r.readThrough(']'); 79 | r.expect(": "); 80 | String rest = r.readRemaining(); 81 | // TODO message filtering 82 | }catch(RuntimeException e){ 83 | System.err.println("Warning: Invalid console output: " + clean); 84 | e.printStackTrace(); 85 | } 86 | } 87 | 88 | public void handlePluginMessage(InternalMessage message){ 89 | switch(message.getType()){ 90 | case SERVER_STARTED: 91 | if(state == ServerState.STATE_STARTING){ 92 | nextState(); 93 | }else{ 94 | new RuntimeException("Unexpected SERVER_STARTED message received while server is in " + state.name()).printStackTrace(); 95 | } 96 | break; 97 | case PLUGIN_DISABLED: 98 | setStateStopping(); 99 | break; 100 | case PLAYER_JOIN: 101 | // TODO: handle 102 | break; 103 | case PLAYER_QUIT: 104 | // TODO: handle 105 | break; 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/main/java/com/github/pemapmodder/pocketminegui/gui/server/ServerMainActivity.java: -------------------------------------------------------------------------------- 1 | package com.github.pemapmodder.pocketminegui.gui.server; 2 | 3 | /* 4 | * This file is part of PocketMine-GUI. 5 | * 6 | * PocketMine-GUI is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PocketMine-GUI is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with PocketMine-GUI. If not, see . 18 | */ 19 | 20 | import com.github.pemapmodder.pocketminegui.lib.Activity; 21 | import com.github.pemapmodder.pocketminegui.utils.NonBlockingANSIReader; 22 | import lombok.Getter; 23 | import org.apache.commons.io.IOUtils; 24 | 25 | import javax.swing.JButton; 26 | import javax.swing.JMenu; 27 | import javax.swing.JMenuBar; 28 | import java.awt.GridBagConstraints; 29 | import java.awt.GridBagLayout; 30 | import java.awt.event.KeyEvent; 31 | import java.io.*; 32 | 33 | public class ServerMainActivity extends Activity{ 34 | @Getter private Process process; 35 | @Getter private OutputStream stdin; 36 | @Getter private InputStream stdout; 37 | @Getter private NonBlockingANSIReader stdoutBuffered; 38 | 39 | // @Getter private ServerState serverState = ServerState.STATE_STOPPED; 40 | @Getter private ServerLifetime lifetime; 41 | private File home; 42 | 43 | private File phpBinaries, pmEntry; 44 | @Getter private JButton startStopButton; 45 | @Getter private ConsolePanel consolePanel; 46 | 47 | public ServerMainActivity(File home, File phpBinaries){ 48 | super("PocketMine-GUI @ " + home.getAbsolutePath()); 49 | this.home = home; 50 | this.phpBinaries = phpBinaries; 51 | pmEntry = new File(home, "PocketMine-MP.phar"); 52 | if(!pmEntry.isFile()){ 53 | pmEntry = new File(home, "src"); 54 | if(!pmEntry.isDirectory()){ 55 | throw new RuntimeException("No PocketMine entry detected"); 56 | } 57 | pmEntry = new File(pmEntry, "pocketmine/PocketMine.php"); 58 | } 59 | File pluginPath = new File(home, "plugins/.pmgui.adaptor.php"); 60 | pluginPath.getParentFile().mkdirs(); 61 | try{ 62 | IOUtils.copy(getClass().getClassLoader().getResourceAsStream("plugins/adaptor.php"), new FileOutputStream(pluginPath)); 63 | }catch(IOException e){ 64 | e.printStackTrace(); 65 | } 66 | } 67 | 68 | @Override 69 | protected void onStart(){ 70 | lifetime = new ServerLifetime(this); 71 | 72 | // setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS)); 73 | setLayout(new GridBagLayout()); 74 | JMenuBar bar = new JMenuBar(); 75 | JMenu serverMenu = new JMenu("Server"); 76 | serverMenu.setMnemonic(KeyEvent.VK_S); 77 | JMenu playerMenu = new JMenu("Players"); 78 | playerMenu.setMnemonic(KeyEvent.VK_P); 79 | bar.add(serverMenu); 80 | bar.add(playerMenu); 81 | setJMenuBar(bar); 82 | 83 | startStopButton = new JButton("Start"); 84 | startStopButton.addActionListener(lifetime::listen); 85 | GridBagConstraints constr = new GridBagConstraints(); 86 | constr.gridx = 0; 87 | constr.gridy = 0; 88 | constr.fill = GridBagConstraints.VERTICAL; 89 | constr.weighty = 0.02; 90 | constr.weightx = 0.1; 91 | add(startStopButton, constr); 92 | constr.gridx = 1; 93 | constr.gridy = 1; 94 | constr.fill = GridBagConstraints.BOTH; 95 | constr.weightx = 0.8; 96 | constr.weighty = 0.9; 97 | add(consolePanel = new ConsolePanel(this), constr); 98 | } 99 | 100 | boolean startServer(){ 101 | try{ 102 | System.err.println("Starting server: " + phpBinaries.getAbsolutePath() + " " + pmEntry.getAbsolutePath()); 103 | setProcess(new ProcessBuilder 104 | (phpBinaries.getAbsolutePath(), pmEntry.getAbsolutePath(), 105 | "--enable-ansi", "--disable-readline", "--disable-wizard", "--pmgui.enabled=1") 106 | .directory(home) 107 | .redirectErrorStream(true) 108 | .start()); 109 | }catch(IOException e){ 110 | e.printStackTrace(); 111 | } 112 | return true; 113 | } 114 | 115 | public void setProcess(Process process){ 116 | this.process = process; 117 | stdin = process.getOutputStream(); 118 | stdout = process.getInputStream(); 119 | stdoutBuffered = new NonBlockingANSIReader(stdout); 120 | stdoutBuffered.start(); 121 | } 122 | 123 | @Override 124 | public void pack(){ 125 | super.pack(); 126 | setExtendedState(MAXIMIZED_BOTH); 127 | } 128 | 129 | public enum ServerState{ 130 | STATE_STOPPED("Start"), 131 | STATE_STARTING("Starting..."), 132 | STATE_RUNNING("Stop"), 133 | STATE_STOPPING("Stopping..."); 134 | 135 | @Getter private String buttonName; 136 | 137 | ServerState(String buttonName){ 138 | this.buttonName = buttonName; 139 | } 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /src/main/java/com/github/pemapmodder/pocketminegui/gui/startup/ChooseServerActivity.java: -------------------------------------------------------------------------------- 1 | package com.github.pemapmodder.pocketminegui.gui.startup; 2 | 3 | /* 4 | * This file is part of PocketMine-GUI. 5 | * 6 | * PocketMine-GUI is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PocketMine-GUI is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with PocketMine-GUI. If not, see . 18 | */ 19 | 20 | import com.github.pemapmodder.pocketminegui.gui.server.ServerMainActivity; 21 | import com.github.pemapmodder.pocketminegui.gui.startup.installer.InstallServerActivity; 22 | import com.github.pemapmodder.pocketminegui.lib.Activity; 23 | import com.github.pemapmodder.pocketminegui.utils.Utils; 24 | 25 | import javax.swing.*; 26 | import java.awt.Font; 27 | import java.awt.GridLayout; 28 | import java.awt.event.ActionEvent; 29 | import java.awt.event.ActionListener; 30 | import java.io.File; 31 | 32 | import static com.github.pemapmodder.pocketminegui.utils.Utils.OperatingSystem.WINDOWS; 33 | import static com.github.pemapmodder.pocketminegui.utils.Utils.exec; 34 | import static com.github.pemapmodder.pocketminegui.utils.Utils.validatePhpBinaries; 35 | import static javax.swing.JFileChooser.APPROVE_OPTION; 36 | import static javax.swing.JFileChooser.CANCEL_OPTION; 37 | import static javax.swing.JFileChooser.DIRECTORIES_ONLY; 38 | import static javax.swing.JFileChooser.ERROR_OPTION; 39 | import static javax.swing.JFileChooser.FILES_ONLY; 40 | import static javax.swing.JOptionPane.ERROR_MESSAGE; 41 | import static javax.swing.JOptionPane.WARNING_MESSAGE; 42 | import static javax.swing.JOptionPane.showMessageDialog; 43 | 44 | public class ChooseServerActivity extends Activity{ 45 | public ChooseServerActivity(){ 46 | super("PocketMine-GUI"); 47 | } 48 | 49 | @Override 50 | protected void onStart(){ 51 | setLayout(new GridLayout(3, 1)); 52 | JLabel titleLabel = new JLabel("PocketMine-GUI"); 53 | titleLabel.setFont(new Font("Helvetica", Font.BOLD, 24)); 54 | titleLabel.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0)); 55 | titleLabel.setHorizontalAlignment(SwingConstants.CENTER); 56 | add(titleLabel); 57 | JButton chooseServer = new JButton("Choose server directory"); 58 | chooseServer.addActionListener(new ChooseServerOnClickListener()); 59 | add(chooseServer); 60 | JButton installServer = new JButton("Install server into new directory"); 61 | installServer.addActionListener(new InstallServerOnClickListener()); 62 | add(installServer); 63 | } 64 | 65 | private class ChooseServerOnClickListener implements ActionListener{ 66 | @Override 67 | public void actionPerformed(ActionEvent e){ 68 | JFileChooser chooser = new JFileChooser(new File(".")); 69 | chooser.setFileSelectionMode(DIRECTORIES_ONLY); 70 | int ret = chooser.showOpenDialog(ChooseServerActivity.this); 71 | if(ret == CANCEL_OPTION || ret == ERROR_OPTION){ 72 | return; 73 | } 74 | File home = chooser.getSelectedFile(); 75 | if(!home.isDirectory()){ 76 | showMessageDialog(ChooseServerActivity.this, "Not a directory!", 77 | "Invalid selection", ERROR_MESSAGE); 78 | return; 79 | } 80 | if(!new File(home, "PocketMine-MP.phar").isFile() && !new File(home, "src").isDirectory()){ 81 | showMessageDialog(ChooseServerActivity.this, "Could not find a phar or " + 82 | "source installation of PocketMine-MP in directory! " + 83 | "Please click the \"Install server into new directory\" button if " + 84 | "you wish to install a server there instead.", "Invalid selection", ERROR_MESSAGE); 85 | return; 86 | } 87 | File phpBinaries = new File(home, "bin/php/php.exe"); 88 | if(!phpBinaries.isFile()){ 89 | phpBinaries = new File(home, "bin/php5/bin/php"); 90 | if(!phpBinaries.isFile()){ 91 | String pathPhp = exec(Utils.getOS() == WINDOWS ? "where php" : "which php"); 92 | if(pathPhp != null){ 93 | phpBinaries = new File(pathPhp); 94 | if(!phpBinaries.isFile() || !validatePhpBinaries(phpBinaries)){ 95 | showMessageDialog(ChooseServerActivity.this, "Could not autodetect PHP binaries. " + 96 | "Please choose the PHP binaries to run with this server.", 97 | "Binaries not found", WARNING_MESSAGE); 98 | while(true){ 99 | JFileChooser binChooser = new JFileChooser(new File( 100 | System.getProperty("os.name").toLowerCase().contains("win") ? 101 | System.getenv("ProgramFiles") : "/Applications")); 102 | binChooser.setFileSelectionMode(FILES_ONLY); 103 | ret = binChooser.showOpenDialog(ChooseServerActivity.this); 104 | if(ret != APPROVE_OPTION){ 105 | return; 106 | } 107 | phpBinaries = binChooser.getSelectedFile(); 108 | if(validatePhpBinaries(phpBinaries)){ 109 | break; 110 | } 111 | showMessageDialog(ChooseServerActivity.this, "Invalid PHP binaries! " + 112 | "Please choose again.", "Invalid binaries", ERROR_MESSAGE); 113 | } 114 | } 115 | } 116 | } 117 | } 118 | ServerMainActivity server = new ServerMainActivity(home, phpBinaries); 119 | initNewActivity(server); 120 | } 121 | } 122 | 123 | private class InstallServerOnClickListener implements ActionListener{ 124 | @Override 125 | public void actionPerformed(ActionEvent e){ 126 | new InstallServerActivity(ChooseServerActivity.this).init(); 127 | } 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/main/java/com/github/pemapmodder/pocketminegui/gui/startup/config/ServerOptionsActivity.java: -------------------------------------------------------------------------------- 1 | package com.github.pemapmodder.pocketminegui.gui.startup.config; 2 | 3 | /* 4 | * This file is part of PocketMine-GUI. 5 | * 6 | * PocketMine-GUI is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PocketMine-GUI is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with PocketMine-GUI. If not, see . 18 | */ 19 | 20 | import com.github.pemapmodder.pocketminegui.gui.startup.config.adaptor.CheckBoxOptionAdaptor; 21 | import com.github.pemapmodder.pocketminegui.gui.startup.config.adaptor.NumberFieldAdaptor; 22 | import com.github.pemapmodder.pocketminegui.gui.startup.config.adaptor.OptionAdaptor; 23 | import com.github.pemapmodder.pocketminegui.lib.Activity; 24 | import com.github.pemapmodder.pocketminegui.lib.JNumberFilter; 25 | import lombok.Getter; 26 | 27 | import javax.swing.*; 28 | import java.awt.GridLayout; 29 | import java.util.List; 30 | import java.util.Map; 31 | 32 | public abstract class ServerOptionsActivity extends Activity{ 33 | @Getter private final Map values; 34 | @Getter private final Map descMap; 35 | 36 | @Getter private JLabel descLabel; 37 | @Getter private JPanel editorPanel; 38 | 39 | @Getter private OptionAdaptor adaptor; 40 | 41 | private int lastSelected = -1; 42 | 43 | public ServerOptionsActivity(String title, Activity activity, Map map, Map descMap){ 44 | super(title, activity); 45 | values = map; 46 | this.descMap = descMap; 47 | } 48 | 49 | @Override 50 | protected void onStart(){ 51 | getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS)); 52 | JPanel properties = new JPanel(); 53 | descLabel = new JLabel(); 54 | editorPanel = new JPanel(); 55 | JScrollPane pane = new JScrollPane(); 56 | DefaultListModel model = new DefaultListModel<>(); 57 | JList list = new JList<>(); 58 | list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 59 | list.setSize(list.getWidth(), 300); 60 | list.addListSelectionListener(e -> onSelect(list.getSelectedIndex())); 61 | values.keySet().forEach(model::addElement); 62 | list.setModel(model); 63 | list.revalidate(); 64 | list.repaint(); 65 | pane.getViewport().add(list); 66 | properties.add(pane); 67 | add(properties); 68 | JPanel detailsPanel = new JPanel(new GridLayout(1, 2)); 69 | detailsPanel.add(descLabel); 70 | detailsPanel.add(editorPanel); 71 | add(detailsPanel); 72 | onSelect(0); 73 | setExtendedState(MAXIMIZED_BOTH); 74 | } 75 | 76 | private void onSelect(int index){ 77 | if(lastSelected == index){ 78 | return; 79 | } 80 | if(lastSelected != -1){ 81 | onDeselect(lastSelected); 82 | } 83 | lastSelected = index; 84 | String key = (String) values.keySet().toArray()[index]; 85 | descLabel.setText(descMap.get(key)); 86 | editorPanel.removeAll(); 87 | Object value = values.values().toArray()[index]; 88 | if(value instanceof Boolean){ 89 | JCheckBox checkBox = new JCheckBox("Enable"); 90 | checkBox.setSelected((Boolean) value); 91 | editorPanel.add(checkBox); 92 | adaptor = new CheckBoxOptionAdaptor(checkBox); 93 | }else if(value instanceof Number){ 94 | JTextField field = new JTextField(); 95 | field.setSize(300, field.getHeight()); 96 | field.setDocument(new JNumberFilter().setNegativeAccepted(true)); 97 | editorPanel.add(field); 98 | adaptor = new NumberFieldAdaptor(field); 99 | }else if(value instanceof String){ 100 | JTextField field = new JTextField(); 101 | field.setSize(600, field.getHeight()); 102 | editorPanel.add(field); 103 | adaptor = field::getText; 104 | }else if(value instanceof List){ 105 | // TODO 106 | adaptor = () -> (List) value; 107 | }else{ 108 | adaptor = () -> value; 109 | } 110 | } 111 | 112 | private void onDeselect(int lastSelected){ 113 | String key = (String) values.keySet().toArray()[lastSelected]; 114 | values.put(key, adaptor.getOption()); 115 | } 116 | 117 | @Override 118 | protected void onStop(){ 119 | onResult(values); 120 | } 121 | 122 | protected abstract void onResult(Map opts); 123 | } 124 | -------------------------------------------------------------------------------- /src/main/java/com/github/pemapmodder/pocketminegui/gui/startup/config/adaptor/CheckBoxOptionAdaptor.java: -------------------------------------------------------------------------------- 1 | package com.github.pemapmodder.pocketminegui.gui.startup.config.adaptor; 2 | 3 | /* 4 | * This file is part of PocketMine-GUI. 5 | * 6 | * PocketMine-GUI is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PocketMine-GUI is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with PocketMine-GUI. If not, see . 18 | */ 19 | 20 | import lombok.AllArgsConstructor; 21 | import lombok.Getter; 22 | 23 | import javax.swing.JCheckBox; 24 | 25 | @AllArgsConstructor 26 | public class CheckBoxOptionAdaptor implements OptionAdaptor{ 27 | @Getter private JCheckBox checkBox; 28 | 29 | @Override 30 | public Boolean getOption(){ 31 | return checkBox.isSelected(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/github/pemapmodder/pocketminegui/gui/startup/config/adaptor/NumberFieldAdaptor.java: -------------------------------------------------------------------------------- 1 | package com.github.pemapmodder.pocketminegui.gui.startup.config.adaptor; 2 | 3 | /* 4 | * This file is part of PocketMine-GUI. 5 | * 6 | * PocketMine-GUI is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PocketMine-GUI is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with PocketMine-GUI. If not, see . 18 | */ 19 | 20 | import lombok.AllArgsConstructor; 21 | 22 | import javax.swing.JTextField; 23 | 24 | @AllArgsConstructor 25 | public class NumberFieldAdaptor implements OptionAdaptor{ 26 | private JTextField field; 27 | 28 | @Override 29 | public Number getOption(){ 30 | String text = field.getText(); 31 | double dbl = Double.parseDouble(text); 32 | if(Integer.MIN_VALUE <= dbl && dbl <= Integer.MAX_VALUE){ 33 | return (int) dbl; 34 | } 35 | return dbl; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/github/pemapmodder/pocketminegui/gui/startup/config/adaptor/OptionAdaptor.java: -------------------------------------------------------------------------------- 1 | package com.github.pemapmodder.pocketminegui.gui.startup.config.adaptor; 2 | 3 | /* 4 | * This file is part of PocketMine-GUI. 5 | * 6 | * PocketMine-GUI is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PocketMine-GUI is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with PocketMine-GUI. If not, see . 18 | */ 19 | 20 | public interface OptionAdaptor{ 21 | public T getOption(); 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/github/pemapmodder/pocketminegui/gui/startup/installer/FetchVersionsThread.java: -------------------------------------------------------------------------------- 1 | package com.github.pemapmodder.pocketminegui.gui.startup.installer; 2 | 3 | /* 4 | * This file is part of PocketMine-GUI. 5 | * 6 | * PocketMine-GUI is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PocketMine-GUI is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with PocketMine-GUI. If not, see . 18 | */ 19 | 20 | import com.github.pemapmodder.pocketminegui.gui.startup.installer.cards.ChooseVersionCard; 21 | import lombok.Getter; 22 | import org.apache.commons.io.IOUtils; 23 | import org.json.JSONArray; 24 | import org.json.JSONException; 25 | import org.json.JSONObject; 26 | 27 | import java.io.IOException; 28 | import java.net.MalformedURLException; 29 | import java.net.URL; 30 | import java.text.DateFormat; 31 | import java.text.ParseException; 32 | import java.text.SimpleDateFormat; 33 | import java.util.ArrayList; 34 | import java.util.List; 35 | 36 | public class FetchVersionsThread extends Thread{ 37 | @Getter 38 | private final ChooseVersionCard card; 39 | @Getter 40 | private final List releases = new ArrayList<>(); 41 | @Getter 42 | private boolean done = false; 43 | 44 | public FetchVersionsThread(ChooseVersionCard card){ 45 | this.card = card; 46 | } 47 | 48 | @Override 49 | public void run(){ 50 | fetchGitHubReleases(); 51 | fetchJenkinsBuilds("http://jenkins.pocketmine.net/job/PocketMine-MP/api/json?depth=1", "dev", ReleaseType.DEVELOPMENT); 52 | fetchJenkinsBuilds("http://jenkins.pocketmine.net/job/PocketMine-MP-Bleeding/api/json?depth=1", "bleeding", ReleaseType.BLEEDING); 53 | fetchPmbBuilds(); 54 | done = true; 55 | } 56 | 57 | private void fetchGitHubReleases(){ 58 | try{ 59 | URL url = new URL("https://api.github.com/repos/PocketMine/PocketMine-MP/releases"); 60 | String jsonString = IOUtils.toString(url); 61 | JSONArray releasesArray = new JSONArray(jsonString); 62 | for(Object object : releasesArray){ 63 | JSONObject jo = (JSONObject) object; 64 | DateFormat date = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); 65 | JSONArray assets = jo.getJSONArray("assets"); 66 | String pharUrl = null; 67 | for(Object asset : assets){ 68 | JSONObject assetObject = (JSONObject) asset; 69 | if(assetObject.getString("name").endsWith(".phar")){ 70 | pharUrl = assetObject.getString("browser_download_url"); 71 | } 72 | } 73 | if(pharUrl == null){ 74 | continue; 75 | } 76 | Release release = new Release( 77 | jo.getString("tag_name"), 78 | jo.getBoolean("prerelease") ? ReleaseType.BETA : ReleaseType.STABLE, 79 | date.parse(jo.getString("published_at")).getTime(), 80 | pharUrl 81 | ); 82 | synchronized(releases){ 83 | releases.add(release); 84 | } 85 | } 86 | }catch(IOException e){ 87 | e.printStackTrace(); 88 | }catch(NullPointerException | ClassCastException | JSONException | ParseException e){ 89 | System.err.println("GitHub API returned invalid value!"); 90 | e.printStackTrace(); 91 | } 92 | } 93 | 94 | private void fetchJenkinsBuilds(String urlPath, String buildPrefix, ReleaseType releaseType){ 95 | try{ 96 | URL url = new URL(urlPath); 97 | String jsonString = IOUtils.toString(url); 98 | JSONObject object = new JSONObject(jsonString); 99 | JSONArray array = object.getJSONArray("builds"); 100 | for(Object arrayObject : array){ 101 | JSONObject build = (JSONObject) arrayObject; 102 | if(!build.getString("result").equals("SUCCESS")){ 103 | continue; 104 | } 105 | String artifactName = null; 106 | for(Object artifactObject : build.getJSONArray("artifacts")){ 107 | JSONObject artifact = (JSONObject) artifactObject; 108 | if(artifact.getString("fileName").endsWith(".phar")){ 109 | artifactName = artifact.getString("relativePath"); 110 | } 111 | } 112 | if(artifactName == null){ 113 | continue; 114 | } 115 | Release release = new Release( 116 | buildPrefix + "-" + build.getInt("number"), 117 | releaseType, 118 | build.getLong("timestamp"), 119 | build.getString("url") + "artifact/" + artifactName 120 | ); 121 | synchronized(releases){ 122 | releases.add(release); 123 | } 124 | } 125 | }catch(MalformedURLException e){ 126 | e.printStackTrace(); 127 | }catch(IOException | JSONException | NullPointerException | ClassCastException e){ 128 | if(e.getMessage().startsWith("Server returned HTTP response code: 521")){ 129 | System.err.println("Jenkins server is down!"); 130 | return; 131 | } 132 | System.err.println("Jenkins API returned invalid value, resulting in this error: "); 133 | e.printStackTrace(); 134 | } 135 | } 136 | 137 | public final static int PMB_TYPE_MASTER = 0; 138 | public final static int PMB_TYPE_BRANCH = 1; 139 | public final static int PMB_TYPE_PR = 2; 140 | 141 | private void fetchPmbBuilds(){ 142 | try{ 143 | URL url = new URL("http://pmt.mcpe.me/pmb/versions.php"); 144 | String source = IOUtils.toString(url); 145 | JSONObject object = new JSONObject(source); 146 | JSONArray versions = object.getJSONArray("versions"); 147 | for(Object obj : versions){ 148 | JSONObject version = (JSONObject) obj; 149 | String branch = version.getString("branch"); 150 | int type = version.getInt("buildType"); 151 | String name; 152 | if(type == PMB_TYPE_MASTER){ 153 | name = "Latest development build"; 154 | }else if(type == PMB_TYPE_BRANCH){ 155 | name = "Unstable build for branch " + branch; 156 | }else if(type == PMB_TYPE_PR){ 157 | name = "Unverified build for pull request #" + version.getInt("id") + " by @" + version.getString("actor") + ": " + version.getString("title"); 158 | }else{ 159 | throw new UnsupportedOperationException("Unknown build type " + type); 160 | } 161 | Release release = new Release(name, ReleaseType.PMB, version.getLong("time") * 1000, 162 | "http://pmt.mcpe.me/pmb/dl/" + branch + ".phar"); 163 | synchronized(releases){ 164 | releases.add(release); 165 | } 166 | } 167 | }catch(IOException | ClassCastException e){ 168 | e.printStackTrace(); 169 | } 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /src/main/java/com/github/pemapmodder/pocketminegui/gui/startup/installer/InstallPHPThread.java: -------------------------------------------------------------------------------- 1 | package com.github.pemapmodder.pocketminegui.gui.startup.installer; 2 | 3 | /* 4 | * This file is part of PocketMine-GUI. 5 | * 6 | * PocketMine-GUI is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PocketMine-GUI is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with PocketMine-GUI. If not, see . 18 | */ 19 | 20 | import com.github.pemapmodder.pocketminegui.utils.AsyncTask; 21 | import com.github.pemapmodder.pocketminegui.utils.Utils; 22 | import lombok.Getter; 23 | import lombok.RequiredArgsConstructor; 24 | 25 | import java.io.File; 26 | 27 | @RequiredArgsConstructor 28 | public class InstallPHPThread extends AsyncTask{ 29 | private final File home; 30 | @Getter private File result = null; 31 | @Getter private boolean initialized; 32 | 33 | @Override 34 | public void run(){ 35 | setMax(100); 36 | setProgress(0); 37 | initialized = true; 38 | Utils.installPHP(home, new Utils.InstallProgressReporter(){ 39 | @Override 40 | public void report(double fraction){ 41 | setProgress((int) (fraction * 100)); 42 | } 43 | 44 | @Override 45 | public void completed(File result){ 46 | setProgress(100); 47 | InstallPHPThread.this.result = result; 48 | } 49 | 50 | @Override 51 | public void errored(){ 52 | setProgress(100); 53 | } 54 | }); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/com/github/pemapmodder/pocketminegui/gui/startup/installer/InstallServerActivity.java: -------------------------------------------------------------------------------- 1 | package com.github.pemapmodder.pocketminegui.gui.startup.installer; 2 | 3 | /* 4 | * This file is part of PocketMine-GUI. 5 | * 6 | * PocketMine-GUI is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PocketMine-GUI is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with PocketMine-GUI. If not, see . 18 | */ 19 | 20 | 21 | import com.github.pemapmodder.pocketminegui.gui.server.ServerMainActivity; 22 | import com.github.pemapmodder.pocketminegui.gui.startup.installer.cards.*; 23 | import com.github.pemapmodder.pocketminegui.lib.Activity; 24 | import com.github.pemapmodder.pocketminegui.lib.card.Card; 25 | import com.github.pemapmodder.pocketminegui.lib.card.CardActivity; 26 | import lombok.Getter; 27 | import lombok.Setter; 28 | 29 | import java.io.File; 30 | 31 | public class InstallServerActivity extends CardActivity{ 32 | @Getter private File selectedHome; 33 | @Getter @Setter private File phpBinaries; 34 | @Getter @Setter private Release selectedRelease; 35 | 36 | public InstallServerActivity(Activity parent){ 37 | super("Install server", parent); 38 | setExtendedState(MAXIMIZED_BOTH); 39 | } 40 | 41 | @Override 42 | public Card[] getDefaultCards(){ 43 | return new Card[]{ 44 | new ChooseLocationCard(this), 45 | new ChooseVersionCard(this), 46 | new DownloadProgressCard(this), 47 | new PhpInstallerCard(this), 48 | new ServerSetupCard(this), 49 | }; 50 | } 51 | 52 | public void setSelectedHome(File selectedHome){ 53 | this.selectedHome = selectedHome; 54 | selectedHome.mkdirs(); 55 | } 56 | 57 | @Override 58 | protected void setCard(int index, int exitType){ 59 | super.setCard(index, exitType); 60 | setExtendedState(MAXIMIZED_BOTH); 61 | } 62 | 63 | @Override 64 | protected void onFinish(){ 65 | super.onFinish(); 66 | getParent().initNewActivity(new ServerMainActivity(selectedHome, phpBinaries)); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/com/github/pemapmodder/pocketminegui/gui/startup/installer/Release.java: -------------------------------------------------------------------------------- 1 | package com.github.pemapmodder.pocketminegui.gui.startup.installer; 2 | 3 | /* 4 | * This file is part of PocketMine-GUI. 5 | * 6 | * PocketMine-GUI is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PocketMine-GUI is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with PocketMine-GUI. If not, see . 18 | */ 19 | 20 | import lombok.AllArgsConstructor; 21 | import lombok.Getter; 22 | 23 | import java.text.SimpleDateFormat; 24 | import java.util.Date; 25 | 26 | @AllArgsConstructor 27 | public class Release{ 28 | public final static int LIST_STABLE = 0, LIST_BETA = 1, LIST_DEVELOPMENT = 2, LIST_BLEEDING = 3, LIST_PMB = 4; 29 | 30 | @Getter private String name; 31 | @Getter private ReleaseType type; 32 | @Getter private long publishTime; 33 | @Getter private String pharUrl; 34 | 35 | @Override 36 | public String toString(){ 37 | return "" + name + "
" + "" + 38 | "
" + type.getName() + " version" + 39 | new SimpleDateFormat("YYYY-MM-dd HH:mm:ss z").format(new Date(publishTime)) + 40 | "
"; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/github/pemapmodder/pocketminegui/gui/startup/installer/ReleaseType.java: -------------------------------------------------------------------------------- 1 | package com.github.pemapmodder.pocketminegui.gui.startup.installer; 2 | 3 | /* 4 | * This file is part of PocketMine-GUI. 5 | * 6 | * PocketMine-GUI is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PocketMine-GUI is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with PocketMine-GUI. If not, see . 18 | */ 19 | 20 | import lombok.Getter; 21 | 22 | import java.awt.event.KeyEvent; 23 | 24 | public enum ReleaseType{ 25 | STABLE("Stable", Release.LIST_STABLE, KeyEvent.VK_S), 26 | BETA("Beta", Release.LIST_BETA, KeyEvent.VK_E), 27 | DEVELOPMENT("Development", Release.LIST_DEVELOPMENT, KeyEvent.VK_D), 28 | BLEEDING("Bleeding", Release.LIST_BLEEDING, KeyEvent.VK_L), 29 | PMB("pmt.mcpe.me/pmb", Release.LIST_PMB, KeyEvent.VK_P); 30 | 31 | @Getter private final String name; 32 | @Getter private final int mnemonic; 33 | @Getter private final int typeId; 34 | 35 | ReleaseType(String name, int typeId, int mnemonic){ 36 | this.name = name; 37 | this.typeId = typeId; 38 | this.mnemonic = mnemonic; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/github/pemapmodder/pocketminegui/gui/startup/installer/cards/ChooseLocationCard.java: -------------------------------------------------------------------------------- 1 | package com.github.pemapmodder.pocketminegui.gui.startup.installer.cards; 2 | 3 | /* 4 | * This file is part of PocketMine-GUI. 5 | * 6 | * PocketMine-GUI is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PocketMine-GUI is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with PocketMine-GUI. If not, see . 18 | */ 19 | 20 | import com.github.pemapmodder.pocketminegui.gui.startup.installer.InstallServerActivity; 21 | import com.github.pemapmodder.pocketminegui.lib.card.Card; 22 | 23 | import javax.swing.*; 24 | import java.awt.event.ActionEvent; 25 | import java.awt.event.ActionListener; 26 | import java.io.File; 27 | 28 | public class ChooseLocationCard extends Card implements ActionListener{ 29 | private final JTextField pathField; 30 | private final InstallServerActivity activity; 31 | 32 | public ChooseLocationCard(InstallServerActivity activity){ 33 | this.activity = activity; 34 | JLabel installLabel = new JLabel("Install server at: "); 35 | add(installLabel); 36 | JPanel pathPanel = new JPanel(); 37 | pathField = new JTextField(); 38 | pathField.setText(new File(".", "PocketMine-MP/").getAbsolutePath()); 39 | pathPanel.add(pathField); 40 | JButton pathButton = new JButton("..."); 41 | pathButton.addActionListener(this); 42 | pathPanel.add(pathButton); 43 | add(pathPanel); 44 | } 45 | 46 | @Override 47 | public String getCardName(){ 48 | return "Choose install location"; 49 | } 50 | 51 | @Override 52 | public void actionPerformed(ActionEvent e){ 53 | JFileChooser chooser = new JFileChooser(new File(".")); 54 | chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); 55 | int result = chooser.showDialog(this, "Choose"); 56 | if(result == JFileChooser.APPROVE_OPTION){ 57 | File file = chooser.getSelectedFile(); 58 | pathField.setText(file.getAbsolutePath()); 59 | activity.pack(); 60 | } 61 | } 62 | 63 | @Override 64 | public boolean onExit(int type){ 65 | activity.setSelectedHome(new File(pathField.getText())); 66 | return super.onExit(type); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/com/github/pemapmodder/pocketminegui/gui/startup/installer/cards/ChooseVersionCard.java: -------------------------------------------------------------------------------- 1 | package com.github.pemapmodder.pocketminegui.gui.startup.installer.cards; 2 | 3 | /* 4 | * This file is part of PocketMine-GUI. 5 | * 6 | * PocketMine-GUI is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PocketMine-GUI is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with PocketMine-GUI. If not, see . 18 | */ 19 | 20 | import com.github.pemapmodder.pocketminegui.gui.startup.installer.FetchVersionsThread; 21 | import com.github.pemapmodder.pocketminegui.gui.startup.installer.InstallServerActivity; 22 | import com.github.pemapmodder.pocketminegui.gui.startup.installer.Release; 23 | import com.github.pemapmodder.pocketminegui.gui.startup.installer.ReleaseType; 24 | import com.github.pemapmodder.pocketminegui.lib.card.Card; 25 | import lombok.Getter; 26 | 27 | import javax.swing.*; 28 | import java.awt.CardLayout; 29 | import java.util.List; 30 | 31 | public class ChooseVersionCard extends Card{ 32 | private final InstallServerActivity activity; 33 | @Getter 34 | private final FetchVersionsThread versionFetch; 35 | @Getter 36 | private int nextIndex = 0; 37 | @Getter 38 | private Timer timer; 39 | private final ButtonGroup typeRadios; 40 | private final JLabel loadingLabel; 41 | private final JPanel cardPanel; 42 | private final CardLayout cardLayout; 43 | private int choosenType = ReleaseType.STABLE.getTypeId(); 44 | private final JList[] lists = new JList[ReleaseType.values().length]; 45 | private final DefaultListModel[] listModels = new DefaultListModel[ReleaseType.values().length]; 46 | @Getter 47 | private Release selectedRelease = null; 48 | 49 | public ChooseVersionCard(InstallServerActivity activity){ 50 | this.activity = activity; 51 | typeRadios = new ButtonGroup(); 52 | JPanel radioPanel = new JPanel(); 53 | cardPanel = new JPanel(cardLayout = new CardLayout()); 54 | for(ReleaseType type : ReleaseType.values()){ 55 | JRadioButton button = new JRadioButton(type.getName()); 56 | button.setMnemonic(type.getMnemonic()); 57 | if(type == ReleaseType.STABLE){ 58 | button.setSelected(true); 59 | } 60 | button.addActionListener(e -> onRadioClicked(type)); 61 | typeRadios.add(button); 62 | radioPanel.add(button); 63 | // int id = type.getTypeId(); 64 | JScrollPane pane = new JScrollPane(); 65 | DefaultListModel model = new DefaultListModel<>(); 66 | listModels[type.getTypeId()] = model; 67 | JList list = new JList<>(); 68 | list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 69 | list.addListSelectionListener(e -> { 70 | Release release = model.get(list.getSelectedIndex()); 71 | activity.setSelectedRelease(release); 72 | activity.getNextButton().setEnabled(true); 73 | }); 74 | pane.getViewport().add(lists[type.getTypeId()] = list); 75 | cardPanel.add(pane, type.getName()); 76 | } 77 | cardLayout.show(cardPanel, ReleaseType.STABLE.getName()); 78 | setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); 79 | add(radioPanel); 80 | add(loadingLabel = new JLabel("Loading...")); 81 | add(cardPanel); 82 | 83 | versionFetch = new FetchVersionsThread(this); 84 | versionFetch.start(); 85 | timer = new Timer(100, e -> updateVersions()); 86 | timer.start(); 87 | } 88 | 89 | private void onRadioClicked(ReleaseType type){ 90 | cardLayout.show(cardPanel, type.getName()); 91 | choosenType = type.getTypeId(); 92 | activity.getNextButton().setEnabled(lists[choosenType].getSelectedIndex() != -1); 93 | } 94 | 95 | private void updateVersions(){ 96 | List releases = versionFetch.getReleases(); 97 | int size = releases.size(); 98 | for(int i = nextIndex; i < size; i++){ 99 | Release release = releases.get(i); 100 | addRelease(release); 101 | } 102 | nextIndex = size; 103 | if(versionFetch.isDone()){ 104 | if(timer != null){ 105 | timer.stop(); 106 | timer = null; 107 | loadingLabel.setText(""); 108 | } 109 | } 110 | } 111 | 112 | @SuppressWarnings("unchecked") 113 | private void addRelease(final Release release){ 114 | int id = release.getType().getTypeId(); 115 | listModels[id].addElement(release); 116 | lists[id].setModel(listModels[id]); 117 | lists[id].revalidate(); 118 | lists[id].repaint(); 119 | } 120 | 121 | @Override 122 | public void onEntry(){ 123 | activity.getNextButton().setText("Install"); 124 | activity.getNextButton().setEnabled(false); 125 | activity.revalidate(); 126 | } 127 | 128 | @Override 129 | public boolean onExit(int type){ 130 | activity.getNextButton().setText("Next"); 131 | activity.revalidate(); 132 | activity.getNextButton().setEnabled(true); 133 | return true; 134 | } 135 | 136 | @Override 137 | public void onStop(){ 138 | if(timer != null){ 139 | timer.stop(); 140 | timer = null; 141 | } 142 | } 143 | 144 | @Override 145 | public String getCardName(){ 146 | return "Choose PocketMine-MP version"; 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /src/main/java/com/github/pemapmodder/pocketminegui/gui/startup/installer/cards/DownloadProgressCard.java: -------------------------------------------------------------------------------- 1 | package com.github.pemapmodder.pocketminegui.gui.startup.installer.cards; 2 | 3 | /* 4 | * This file is part of PocketMine-GUI. 5 | * 6 | * PocketMine-GUI is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PocketMine-GUI is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with PocketMine-GUI. If not, see . 18 | */ 19 | 20 | import com.github.pemapmodder.pocketminegui.gui.startup.installer.InstallServerActivity; 21 | import com.github.pemapmodder.pocketminegui.lib.card.Card; 22 | import com.github.pemapmodder.pocketminegui.utils.GetUrlThread; 23 | 24 | import javax.swing.JLabel; 25 | import javax.swing.JProgressBar; 26 | import javax.swing.Timer; 27 | import java.io.File; 28 | import java.io.FileOutputStream; 29 | import java.io.IOException; 30 | import java.io.OutputStream; 31 | import java.net.MalformedURLException; 32 | import java.net.URL; 33 | 34 | public class DownloadProgressCard extends Card{ 35 | private final InstallServerActivity activity; 36 | private final JProgressBar progressBar; 37 | private final JLabel progressLabel; 38 | private boolean maxSet = false; 39 | private Timer progressCheck; 40 | private GetUrlThread thread; 41 | 42 | public DownloadProgressCard(InstallServerActivity activity){ 43 | this.activity = activity; 44 | add(new JLabel("Downloading... ")); 45 | add(progressBar = new JProgressBar()); 46 | add(progressLabel = new JLabel()); 47 | } 48 | 49 | @Override 50 | public void onEntry(){ 51 | activity.getBackButton().setEnabled(false); 52 | activity.getNextButton().setEnabled(false); 53 | URL url; 54 | try{ 55 | url = new URL(activity.getSelectedRelease().getPharUrl()); 56 | }catch(MalformedURLException e){ 57 | e.printStackTrace(); 58 | return; 59 | } 60 | thread = new GetUrlThread(url); 61 | progressCheck = new Timer(100, ev -> { 62 | if(thread.getMax() > 0){ 63 | if(!maxSet){ 64 | progressBar.setMaximum(thread.getMax()); 65 | maxSet = true; 66 | } 67 | progressBar.setValue(thread.getProgress()); 68 | progressLabel.setText(Math.round(thread.getProgress() / 102.4) / 10.0 + "KB / " + 69 | Math.round(thread.getMax() / 102.4) / 10.0 + "KB"); 70 | if(thread.getMax() == thread.getProgress()){ 71 | progressCheck.stop(); 72 | byte[] data = thread.array; 73 | File home = activity.getSelectedHome(); 74 | try{ 75 | if(!home.mkdirs()){ 76 | // throw new IOException("Cannot make directories"); 77 | } 78 | File phar = new File(home, "PocketMine-MP.phar"); 79 | OutputStream os = new FileOutputStream(phar); 80 | os.write(data); 81 | os.close(); 82 | }catch(IOException e){ 83 | e.printStackTrace(); 84 | } 85 | activity.getNextButton().setEnabled(true); 86 | revalidate(); 87 | } 88 | } 89 | }); 90 | progressCheck.start(); 91 | thread.start(); 92 | } 93 | 94 | @Override 95 | public String getCardName(){ 96 | return "Installing PocketMine-MP..."; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/main/java/com/github/pemapmodder/pocketminegui/gui/startup/installer/cards/PhpInstallerCard.java: -------------------------------------------------------------------------------- 1 | package com.github.pemapmodder.pocketminegui.gui.startup.installer.cards; 2 | 3 | /* 4 | * This file is part of PocketMine-GUI. 5 | * 6 | * PocketMine-GUI is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PocketMine-GUI is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with PocketMine-GUI. If not, see . 18 | */ 19 | 20 | import com.github.pemapmodder.pocketminegui.gui.startup.installer.InstallPHPThread; 21 | import com.github.pemapmodder.pocketminegui.gui.startup.installer.InstallServerActivity; 22 | import com.github.pemapmodder.pocketminegui.lib.card.Card; 23 | import com.github.pemapmodder.pocketminegui.utils.Utils; 24 | 25 | import javax.swing.*; 26 | import java.awt.GridLayout; 27 | import java.io.File; 28 | 29 | public class PhpInstallerCard extends Card{ 30 | private final InstallServerActivity activity; 31 | private final JProgressBar progressBar; 32 | private Timer timer; 33 | private InstallPHPThread thread; 34 | 35 | public PhpInstallerCard(InstallServerActivity activity){ 36 | this.activity = activity; 37 | setLayout(new GridLayout(4, 1)); 38 | add(new JLabel("Do you have PHP binaries on your computer?")); 39 | JButton positive = new JButton("Yes, let me point it to you"); 40 | positive.addActionListener(e -> { 41 | // JOptionPane.showMessageDialog(activity, "Could not autodetect PHP binaries. " + 42 | // "Please choose the PHP binaries to run with this server.", 43 | // "Binaries not found", JOptionPane.WARNING_MESSAGE); 44 | while(true){ 45 | JFileChooser binChooser = new JFileChooser( 46 | // new File(System.getProperty("os.name").toLowerCase().contains("win") ? 47 | // System.getenv("ProgramFiles") : "/Applications") 48 | activity.getSelectedHome() 49 | ); 50 | binChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); 51 | int ret = binChooser.showOpenDialog(activity); 52 | if(ret != JFileChooser.APPROVE_OPTION){ 53 | return; 54 | } 55 | File phpBinaries = binChooser.getSelectedFile(); 56 | if(Utils.validatePhpBinaries(phpBinaries)){ 57 | activity.setPhpBinaries(phpBinaries); 58 | activity.next(); 59 | break; 60 | } 61 | JOptionPane.showMessageDialog(activity, "Invalid PHP binaries! " + 62 | "Please choose again.", "Invalid binaries", JOptionPane.ERROR_MESSAGE); 63 | } 64 | }); 65 | add(positive); 66 | JButton negative = new JButton("No, install it for me"); 67 | negative.addActionListener(e -> { 68 | positive.setEnabled(false); 69 | negative.setEnabled(false); 70 | startInstallation(); 71 | }); 72 | add(negative); 73 | progressBar = new JProgressBar(0, 100); 74 | add(progressBar); 75 | progressBar.setVisible(false); 76 | } 77 | 78 | private void startInstallation(){ 79 | thread = new InstallPHPThread(activity.getSelectedHome()); 80 | timer = new Timer(500, e -> onTimerTick()); 81 | timer.start(); 82 | thread.start(); 83 | progressBar.setVisible(true); 84 | } 85 | 86 | private void onTimerTick(){ 87 | if(thread.isInitialized()){ 88 | progressBar.setValue(thread.getProgress()); 89 | if(thread.getProgress() == thread.getMax()){ 90 | File php = thread.getResult(); 91 | if(php != null){ 92 | activity.setPhpBinaries(php); 93 | } 94 | timer.stop(); 95 | activity.next(); 96 | } 97 | } 98 | } 99 | 100 | @Override 101 | public void onEntry(){ 102 | activity.getNextButton().setEnabled(false); 103 | File home = activity.getSelectedHome(); 104 | String[] paths = System.getProperty("java.library.path").split(";"); 105 | for(String path : paths){ 106 | File file = new File(path, Utils.getOS() == Utils.OperatingSystem.WINDOWS ? "php.exe" : "php"); 107 | if(file.isFile() && Utils.validatePhpBinaries(file)){ 108 | activity.setPhpBinaries(file); 109 | } 110 | } 111 | } 112 | 113 | @Override 114 | public boolean onExit(int type){ 115 | activity.getNextButton().setEnabled(true); 116 | return true; 117 | } 118 | 119 | @Override 120 | public String getCardName(){ 121 | return "PHP Installer"; 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/main/java/com/github/pemapmodder/pocketminegui/gui/startup/installer/cards/ServerSetupCard.java: -------------------------------------------------------------------------------- 1 | package com.github.pemapmodder.pocketminegui.gui.startup.installer.cards; 2 | 3 | /* 4 | * This file is part of PocketMine-GUI. 5 | * 6 | * PocketMine-GUI is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PocketMine-GUI is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with PocketMine-GUI. If not, see . 18 | */ 19 | 20 | import com.github.pemapmodder.pocketminegui.gui.startup.config.ServerOptionsActivity; 21 | import com.github.pemapmodder.pocketminegui.gui.startup.installer.InstallServerActivity; 22 | import com.github.pemapmodder.pocketminegui.lib.card.Card; 23 | import org.apache.commons.lang3.RandomUtils; 24 | import org.yaml.snakeyaml.Yaml; 25 | 26 | import javax.swing.JButton; 27 | import java.io.*; 28 | import java.util.*; 29 | 30 | public class ServerSetupCard extends Card{ 31 | private final static Map SERVER_PROPERTIES_MAP = new HashMap<>(); 32 | private final static Map SERVER_PROPERTIES_DESC_MAP = new HashMap<>(); 33 | private final static Map POCKETMINE_YML_MAP = new HashMap<>(); 34 | private final static Map POCKETMINE_YML_DESC_MAP = new HashMap<>(); 35 | 36 | static{ 37 | initServerPropertiesMap(); 38 | initServerPropertiesDescMap(); 39 | initPocketMineYmlMap(); 40 | initPocketMineYmlDescMap(); 41 | } 42 | 43 | private static void initServerPropertiesMap(){ 44 | SERVER_PROPERTIES_MAP.put("motd", "Minecraft: PE Server"); 45 | SERVER_PROPERTIES_MAP.put("server-port", 19132); 46 | SERVER_PROPERTIES_MAP.put("white-list", false); 47 | SERVER_PROPERTIES_MAP.put("announce-player-achievements", true); 48 | SERVER_PROPERTIES_MAP.put("spawn-protection", 16); 49 | SERVER_PROPERTIES_MAP.put("max-players", 20); 50 | SERVER_PROPERTIES_MAP.put("allow-flight", false); 51 | SERVER_PROPERTIES_MAP.put("spawn-animals", true); 52 | SERVER_PROPERTIES_MAP.put("spawn-mobs", true); 53 | SERVER_PROPERTIES_MAP.put("gamemode", 0); 54 | SERVER_PROPERTIES_MAP.put("force-gamemode", false); 55 | SERVER_PROPERTIES_MAP.put("hardcore", false); 56 | SERVER_PROPERTIES_MAP.put("pvp", true); 57 | SERVER_PROPERTIES_MAP.put("difficulty", 1); 58 | SERVER_PROPERTIES_MAP.put("generator-settings", ""); 59 | SERVER_PROPERTIES_MAP.put("level-name", "world"); 60 | SERVER_PROPERTIES_MAP.put("level-seed", ""); 61 | SERVER_PROPERTIES_MAP.put("level-type", "DEFAULT"); 62 | SERVER_PROPERTIES_MAP.put("enable-query", true); 63 | SERVER_PROPERTIES_MAP.put("enable-rcon", true); 64 | SERVER_PROPERTIES_MAP.put("rcon.password", new String(Base64.getMimeEncoder().encode(RandomUtils.nextBytes(20))).substring(3, 13)); 65 | SERVER_PROPERTIES_MAP.put("auto-save", true); 66 | } 67 | 68 | private static void initServerPropertiesDescMap(){ 69 | SERVER_PROPERTIES_DESC_MAP.put("motd", "Server display name on Minecraft server list"); 70 | SERVER_PROPERTIES_DESC_MAP.put("server-port", "UDP port to run server on"); 71 | SERVER_PROPERTIES_DESC_MAP.put("white-list", "Turn on whitelist. You can manage the whitelist later."); 72 | SERVER_PROPERTIES_DESC_MAP.put("announce-player-achievements", "Whether to broadcast a message when a player has got an achievement"); 73 | SERVER_PROPERTIES_DESC_MAP.put("spawn-protection", "Radius to disallow non-ops to build on"); 74 | SERVER_PROPERTIES_DESC_MAP.put("max-players", "Maximum number of players allowed on the server"); 75 | SERVER_PROPERTIES_DESC_MAP.put("allow-flight", "If set to false, PocketMine will kick players that appear to be flying."); 76 | SERVER_PROPERTIES_DESC_MAP.put("spawn-animals", "whether to spawn animals"); 77 | SERVER_PROPERTIES_DESC_MAP.put("spawn-mobs", "whether to spawn mobs"); 78 | SERVER_PROPERTIES_DESC_MAP.put("gamemode", "Default gamemode of this server.\n0 - survival\n1 - creative\n" + 79 | "2 - adventure mode (cannot break blocks)\n3 - spectator mode (no block breaking, noclip, no PvP, flying)"); 80 | SERVER_PROPERTIES_DESC_MAP.put("force-gamemode", "Whether to set the player back to the old gamemode"); 81 | SERVER_PROPERTIES_DESC_MAP.put("hardcore", "Whether to ban player after he died"); 82 | SERVER_PROPERTIES_DESC_MAP.put("pvp", "Whether to enable PvP"); 83 | SERVER_PROPERTIES_DESC_MAP.put("difficulty", "Difficulty of the server.\n0 - Peaceful mode\n1 - Easy\n2 - Normal\n3 - Hard"); 84 | SERVER_PROPERTIES_DESC_MAP.put("generator-settings", "Superflat formula if level-type is FLAT"); 85 | SERVER_PROPERTIES_DESC_MAP.put("level-name", "Name for the default world"); 86 | SERVER_PROPERTIES_DESC_MAP.put("level-seed", "Seed for the default world (only applies if world is newly generated)"); 87 | SERVER_PROPERTIES_DESC_MAP.put("level-type", "Type for the default world (only applies if world is newly generated)\n" + 88 | "DEFAULT - normal world with terrain\nFLAT - superflat world"); 89 | SERVER_PROPERTIES_DESC_MAP.put("enable-query", "Enable UT3 querying, used by server list websites."); 90 | SERVER_PROPERTIES_DESC_MAP.put("enable-rcon", "Enable RCON, used to connect to console remotely."); 91 | SERVER_PROPERTIES_DESC_MAP.put("rcon.password", "The password to connect with RCON"); 92 | SERVER_PROPERTIES_DESC_MAP.put("auto-save", "Enable auto saving"); 93 | } 94 | 95 | @SuppressWarnings("unchecked") 96 | private static void initPocketMineYmlMap(){ 97 | Yaml yaml = new Yaml(); 98 | Map nest = (Map) yaml.load(ServerSetupCard.class.getClassLoader().getResourceAsStream("pocketmine.yml")); 99 | addNestedToPlain("", nest, POCKETMINE_YML_MAP); 100 | } 101 | 102 | private static void initPocketMineYmlDescMap(){ 103 | POCKETMINE_YML_DESC_MAP.put("settings.language", "Three-letter language code for server-side localization\n" + 104 | "Check your language code on https://en.wikipedia.org/wiki/List_of_ISO_639-2_codes"); 105 | POCKETMINE_YML_DESC_MAP.put("settings.force-language", "Whether to send all text translated to server locale or " + 106 | "let the device handle them"); 107 | POCKETMINE_YML_DESC_MAP.put("settings.shutdown-message", "The kick message when the server stops"); 108 | POCKETMINE_YML_DESC_MAP.put("settings.query-plugins", "Allow listing plugins via Query"); 109 | POCKETMINE_YML_DESC_MAP.put("settings.deprecated-verbose", "Show a console message when a plugin uses " + 110 | "deprecated API methods"); 111 | POCKETMINE_YML_DESC_MAP.put("settings.enable-profiling", "Enable plugin and core profiling by default"); 112 | POCKETMINE_YML_DESC_MAP.put("settings.profile-report-trigger", "Will only add results when tick measurement is " + 113 | "below or equal to given value (default 20)"); 114 | POCKETMINE_YML_DESC_MAP.put("settings.async-workers", "Number of AsyncTask workers.\n" + 115 | "Used for plugin asynchronous tasks, world generation, compression and web communication.\n" + 116 | "Set this approximately to your number of cores.\n" + 117 | "If set to auto, it'll try to detect the number of cores (or use 2)"); 118 | POCKETMINE_YML_DESC_MAP.put("memory.global-limit", "Global soft memory limit in megabytes. Set to 0 to disable\n" + 119 | "This will trigger low-memory-triggers and fire an event to free memory when the usage goes over this"); 120 | POCKETMINE_YML_DESC_MAP.put("memory.main-limit", "Main thread soft memory limit in megabytes. Set to 0 to " + 121 | "disable\nThis will trigger low-memory-triggers and fire an event to free memory when the usage goes over this"); 122 | POCKETMINE_YML_DESC_MAP.put("memory.main-hard-limit", "Main thread hard memory limit in megabytes. Set to 0 to disable\n" + 123 | "This will stop the server when the limit is surpassed"); 124 | POCKETMINE_YML_DESC_MAP.put("memory.check-rate", "Period in ticks to check memory (default 1 second)"); 125 | POCKETMINE_YML_DESC_MAP.put("memory.continuous-trigger", "Continue firing low-memory triggers and event while on low memory"); 126 | POCKETMINE_YML_DESC_MAP.put("memory.continuous-trigger-rate", "Only if memory.continuous-trigger is enabled. " + 127 | "Specifies the rate in memory.check-rate steps (default 30 seconds)"); 128 | POCKETMINE_YML_DESC_MAP.put("memory.garbage-collection.period", "Period in ticks to fire the garbage collector " + 129 | "manually (default 30 minutes), set to 0 to disable\nThis only affect the main thread. Other threads " + 130 | "should fire their own collections"); 131 | POCKETMINE_YML_DESC_MAP.put("memory.garbage-collection.collect-async-worker", "Fire asynchronous tasks to " + 132 | "collect garbage from workers"); 133 | POCKETMINE_YML_DESC_MAP.put("memory.garbage-collection.low-memory-trigger", "Trigger on low memory"); 134 | POCKETMINE_YML_DESC_MAP.put("memory.max-chunks.trigger-limit", "Limit of chunks to load per player, overrides chunk-sending.max-chunks"); 135 | POCKETMINE_YML_DESC_MAP.put("memory.max-chunks.trigger-chunk-collect", "Do chunk garbage collection on trigger"); 136 | POCKETMINE_YML_DESC_MAP.put("memory.max-chunks.low-memory-trigger", "Trigger on low memory"); 137 | POCKETMINE_YML_DESC_MAP.put("memory.world-caches.disable-chunk-cache", "Disable caching chunks"); 138 | POCKETMINE_YML_DESC_MAP.put("memory.world-caches.low-memory-trigger", "Clear cache upon low memory"); 139 | POCKETMINE_YML_DESC_MAP.put("network.batch-threshold", "Threshold for batching packets, in bytes. Only these " + 140 | "packets will be compressed\nSet to 0 to compress everything, -1 to disable."); 141 | POCKETMINE_YML_DESC_MAP.put("network.compression-level", "Compression level used when sending batched packets. " + 142 | "Higher = more CPU, less bandwidth usage"); 143 | POCKETMINE_YML_DESC_MAP.put("network.async-compression", "Use AsyncTasks for compression. Adds half/one tick " + 144 | "delay, less CPU load on main thread"); 145 | POCKETMINE_YML_DESC_MAP.put("network.upnp-forwarding", "Experimental, only for Windows. Tries to use UPnP to " + 146 | "automatically port forward"); 147 | POCKETMINE_YML_DESC_MAP.put("debug.level", "Set to 2 to show debug messages on console, 1 for a cleaner console"); 148 | POCKETMINE_YML_DESC_MAP.put("debug.commands", "Enables these debug commands:\n> /status\n> /gc\n> /dumpmemory"); 149 | // TODO POCKETMINE_YML_DESC_MAP 150 | } 151 | 152 | @SuppressWarnings("unchecked") 153 | public ServerSetupCard(InstallServerActivity activity){ 154 | JButton serverPropertiesButton = new JButton("General server properties"); 155 | serverPropertiesButton.addActionListener(e -> new ServerOptionsActivity("Server properties editor", activity, 156 | new HashMap<>(SERVER_PROPERTIES_MAP), new HashMap<>(SERVER_PROPERTIES_DESC_MAP)){ 157 | @Override 158 | protected void onResult(Map opts){ 159 | try{ 160 | OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream( 161 | new File(activity.getSelectedHome(), "server.properties"))); 162 | writer.append("#Properties Config file\r\n") 163 | .append("#Generated by PocketMine-GUI\r\n"); 164 | for(Map.Entry entry : opts.entrySet()){ 165 | writer.append(entry.getKey()) 166 | .append('=') 167 | .append(entry.getValue().toString()) 168 | .append("\r\n"); 169 | } 170 | writer.close(); 171 | }catch(IOException e1){ 172 | e1.printStackTrace(); 173 | } 174 | } 175 | }.init()); 176 | JButton pocketmineOpts = new JButton("PocketMine-specific settings"); 177 | pocketmineOpts.addActionListener(e -> new ServerOptionsActivity("PocketMine settings editor", activity, 178 | new HashMap<>(POCKETMINE_YML_MAP), new HashMap<>(POCKETMINE_YML_DESC_MAP)){ 179 | @Override 180 | protected void onResult(Map opts){ 181 | Yaml yaml = new Yaml(); 182 | try{ 183 | Writer writer = new OutputStreamWriter(new FileOutputStream(new File(activity.getSelectedHome(), "pocketmine.yml"))); 184 | yaml.dump(convertPlainToNested(opts), writer); 185 | writer.close(); 186 | }catch(IOException e1){ 187 | e1.printStackTrace(); 188 | } 189 | } 190 | }.init()); 191 | add(serverPropertiesButton); 192 | add(pocketmineOpts); 193 | } 194 | 195 | @SuppressWarnings("unchecked") 196 | private static void addNestedToPlain(String prefix, Map nest, Map plain){ 197 | for(Map.Entry entry : nest.entrySet()){ 198 | Object value = entry.getValue(); 199 | if(value instanceof Map){ 200 | addNestedToPlain(prefix + entry.getKey() + ".", (Map) value, plain); 201 | }else{ 202 | plain.put(prefix + entry.getKey(), value); 203 | } 204 | } 205 | } 206 | 207 | @SuppressWarnings("unchecked") 208 | private static Map convertPlainToNested(Map plain){ 209 | Map out = new HashMap<>(); 210 | for(Map.Entry entry : plain.entrySet()){ 211 | Map current = out; 212 | Object value = entry.getValue(); 213 | String[] parts = entry.getKey().split("\\."); 214 | List strings = new ArrayList<>(Arrays.asList(parts)); 215 | while(!strings.isEmpty()){ 216 | String name = strings.remove(0); 217 | if(!current.containsKey(name)){ 218 | if(strings.isEmpty()){ 219 | current.put(name, value); 220 | break; 221 | } 222 | current.put(name, new HashMap()); 223 | } 224 | current = (Map) current.get(name); 225 | } 226 | } 227 | return out; 228 | } 229 | 230 | @Override 231 | public String getCardName(){ 232 | return "Server configuration"; 233 | } 234 | } 235 | -------------------------------------------------------------------------------- /src/main/java/com/github/pemapmodder/pocketminegui/lib/Activity.java: -------------------------------------------------------------------------------- 1 | package com.github.pemapmodder.pocketminegui.lib; 2 | 3 | /* 4 | * This file is part of PocketMine-GUI. 5 | * 6 | * PocketMine-GUI is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PocketMine-GUI is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with PocketMine-GUI. If not, see . 18 | */ 19 | 20 | import com.github.pemapmodder.pocketminegui.PocketMineGUI; 21 | import lombok.Getter; 22 | 23 | import javax.swing.BorderFactory; 24 | import javax.swing.JFrame; 25 | import javax.swing.JPanel; 26 | import javax.swing.border.Border; 27 | import java.awt.event.WindowAdapter; 28 | import java.awt.event.WindowEvent; 29 | 30 | public abstract class Activity extends JFrame{ 31 | @Getter 32 | private Activity parent, child = null; 33 | private boolean hasNewActivity = false; 34 | private boolean onStopCalled = false; 35 | 36 | public Activity(String title){ 37 | this(title, null); 38 | } 39 | 40 | public Activity(String title, Activity parent){ 41 | super(title); 42 | this.parent = parent; 43 | if(parent != null){ 44 | parent.setChild(this); 45 | } 46 | } 47 | 48 | public final void init(){ 49 | if(!hasParent()){ 50 | if(PocketMineGUI.CURRENT_ROOT_ACTIVITY != null){ 51 | throw new IllegalStateException("Cannot init root activity when PocketMineGUI.CURRENT_ROOT_ACTIVITY is not null"); 52 | } 53 | PocketMineGUI.CURRENT_ROOT_ACTIVITY = this; 54 | } 55 | addWindowListener(new InternalWindowListener()); 56 | setLocationRelativeTo(null); 57 | JPanel panel = new JPanel(); 58 | panel.setBorder(getBorder()); 59 | setContentPane(panel); 60 | onStart(); 61 | pack(); 62 | setDefaultCloseOperation(DISPOSE_ON_CLOSE); 63 | setVisible(true); 64 | } 65 | 66 | protected Border getBorder(){ 67 | return BorderFactory.createEmptyBorder(50, 50, 50, 50); 68 | } 69 | 70 | protected void onStart(){ 71 | } 72 | 73 | protected void onFocusGain(){ 74 | } 75 | 76 | protected void onFocusLoss(){ 77 | } 78 | 79 | protected void onStop(){ 80 | } 81 | 82 | protected void onChildClosed(){ 83 | child = null; 84 | } 85 | 86 | public boolean hasParent(){ 87 | return parent != null; 88 | } 89 | 90 | public boolean hasChild(){ 91 | return child != null; 92 | } 93 | 94 | public void setChild(Activity child){ 95 | if(this.child != null){ 96 | throw new IllegalStateException("Activity already has a child"); 97 | } 98 | this.child = child; 99 | } 100 | 101 | public void initNewActivity(Activity successor){ 102 | if(hasParent()){ 103 | parent.initNewActivity(successor); 104 | return; 105 | } 106 | hasNewActivity = true; 107 | stopActivity(); 108 | successor.init(); 109 | } 110 | 111 | public void stopActivity(){ 112 | if(child != null){ 113 | child.stopActivity(); 114 | } 115 | dispose(); 116 | onClose0(); 117 | } 118 | 119 | private void onClose0(){ 120 | if(!onStopCalled){ 121 | onStopCalled = true; 122 | onStop(); 123 | } 124 | if(hasParent()){ 125 | parent.onChildClosed(); 126 | parent.requestFocus(); 127 | }else{ 128 | PocketMineGUI.CURRENT_ROOT_ACTIVITY = null; 129 | if(!hasNewActivity){ 130 | System.exit(0); 131 | } 132 | } 133 | } 134 | 135 | private class InternalWindowListener extends WindowAdapter{ 136 | @Override 137 | public void windowClosed(WindowEvent e){ 138 | onClose0(); 139 | } 140 | 141 | @Override 142 | public void windowGainedFocus(WindowEvent e){ 143 | if(hasChild()){ 144 | child.requestFocus(); 145 | }else{ 146 | onFocusGain(); 147 | } 148 | } 149 | 150 | @Override 151 | public void windowLostFocus(WindowEvent e){ 152 | onFocusLoss(); 153 | } 154 | 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /src/main/java/com/github/pemapmodder/pocketminegui/lib/JNumberFilter.java: -------------------------------------------------------------------------------- 1 | package com.github.pemapmodder.pocketminegui.lib; 2 | 3 | /* 4 | * This file is part of PocketMine-GUI. 5 | * 6 | * PocketMine-GUI is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PocketMine-GUI is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with PocketMine-GUI. If not, see . 18 | */ 19 | 20 | import lombok.Getter; 21 | 22 | import javax.swing.text.AttributeSet; 23 | import javax.swing.text.BadLocationException; 24 | import javax.swing.text.PlainDocument; 25 | 26 | public class JNumberFilter extends PlainDocument{ 27 | @Getter private final static String ACCEPTED_CHARS = "0123456789"; 28 | @Getter private boolean negativeAccepted = false; 29 | 30 | public JNumberFilter setNegativeAccepted(boolean negativeAccepted){ 31 | this.negativeAccepted = negativeAccepted; 32 | return this; 33 | } 34 | 35 | @Override 36 | public void insertString(int offset, String str, AttributeSet attr) throws BadLocationException{ 37 | if(str == null){ 38 | return; 39 | } 40 | for(int i = 0; i < str.length(); i++){ 41 | if(!ACCEPTED_CHARS.contains(String.valueOf(str.charAt(i)))){ 42 | return; 43 | } 44 | } 45 | if(negativeAccepted && str.contains("-")){ 46 | if(str.indexOf("-") != 0 || offset != 0){ 47 | return; 48 | } 49 | } 50 | super.insertString(offset, str, attr); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/github/pemapmodder/pocketminegui/lib/card/Card.java: -------------------------------------------------------------------------------- 1 | package com.github.pemapmodder.pocketminegui.lib.card; 2 | 3 | /* 4 | * This file is part of PocketMine-GUI. 5 | * 6 | * PocketMine-GUI is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PocketMine-GUI is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with PocketMine-GUI. If not, see . 18 | */ 19 | 20 | import javax.swing.JPanel; 21 | 22 | public abstract class Card extends JPanel{ 23 | /** 24 | * The {@link CardActivity} is closed. 25 | */ 26 | public final static int EXIT_CLOSE = 0; 27 | /** 28 | * The "Back" button is triggered. 29 | */ 30 | public final static int EXIT_BACK = 1; 31 | /** 32 | * The "Next" button is triggered. 33 | */ 34 | public final static int EXIT_NEXT = 2; 35 | 36 | public void onEntry(){ 37 | } 38 | 39 | /** 40 | * Triggered when card is swapped 41 | * 42 | * @param type one of {@link #EXIT_CLOSE}, {@link #EXIT_BACK} and {@link #EXIT_NEXT} 43 | * @return whether to allow this action 44 | */ 45 | public boolean onExit(int type){ 46 | return true; 47 | } 48 | 49 | public abstract String getCardName(); 50 | 51 | public void onStop(){ 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/github/pemapmodder/pocketminegui/lib/card/CardActivity.java: -------------------------------------------------------------------------------- 1 | package com.github.pemapmodder.pocketminegui.lib.card; 2 | 3 | /* 4 | * This file is part of PocketMine-GUI. 5 | * 6 | * PocketMine-GUI is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PocketMine-GUI is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with PocketMine-GUI. If not, see . 18 | */ 19 | 20 | import com.github.pemapmodder.pocketminegui.lib.Activity; 21 | import lombok.Getter; 22 | 23 | import javax.swing.BoxLayout; 24 | import javax.swing.JButton; 25 | import javax.swing.JPanel; 26 | import java.awt.CardLayout; 27 | import java.awt.event.KeyEvent; 28 | 29 | public abstract class CardActivity extends Activity{ 30 | @Getter 31 | private Card[] cards; 32 | @Getter 33 | private int currentStep = -1; 34 | @Getter 35 | private JPanel swapper, controls; 36 | @Getter 37 | private JButton backButton, nextButton; 38 | 39 | public CardActivity(String title){ 40 | super(title); 41 | } 42 | 43 | public CardActivity(String title, Activity parent){ 44 | super(title, parent); 45 | } 46 | 47 | public abstract Card[] getDefaultCards(); 48 | 49 | @Override 50 | protected void onStart(){ 51 | cards = getDefaultCards(); 52 | getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS)); 53 | 54 | CardLayout cardLayout = new CardLayout(); 55 | swapper = new JPanel(cardLayout); 56 | for(int i = 0; i < cards.length; i++){ 57 | Card card = cards[i]; 58 | swapper.add(card, "card#" + i); 59 | } 60 | add(swapper); 61 | 62 | controls = new JPanel(); 63 | backButton = new JButton("Back"); 64 | nextButton = new JButton("Next"); 65 | backButton.addActionListener(e -> back()); 66 | backButton.setMnemonic(KeyEvent.VK_B); 67 | nextButton.addActionListener(e -> next()); 68 | nextButton.setMnemonic(KeyEvent.VK_N); 69 | controls.add(backButton); 70 | controls.add(nextButton); 71 | 72 | add(controls); 73 | 74 | setCard(0, 0); // the second parameter simply doesn't matter 75 | } 76 | 77 | public void next(){ 78 | if(currentStep + 1 == cards.length){ 79 | onFinish(); 80 | return; 81 | } 82 | setCard(currentStep + 1, Card.EXIT_NEXT); 83 | } 84 | 85 | public void back(){ 86 | setCard(currentStep - 1, Card.EXIT_BACK); 87 | } 88 | 89 | protected void setCard(int index, int exitType){ 90 | if(index >= cards.length){ 91 | throw new IndexOutOfBoundsException("No such card"); 92 | } 93 | if(currentStep == -1 || cards[currentStep].onExit(exitType)){ 94 | ((CardLayout) swapper.getLayout()).show(swapper, "card#" + index); 95 | currentStep = index; 96 | Card newCard = cards[currentStep]; 97 | newCard.onEntry(); 98 | setTitle(String.format("Step %d of %d: %s", currentStep + 1, cards.length, newCard.getCardName())); 99 | nextButton.setText(currentStep + 1 == cards.length ? "Finish" : "Next"); 100 | backButton.setEnabled(currentStep > 0); 101 | revalidate(); 102 | pack(); 103 | } 104 | } 105 | 106 | @Override 107 | protected void onStop(){ 108 | if(currentStep != -1){ 109 | cards[currentStep].onExit(Card.EXIT_CLOSE); 110 | } 111 | for(Card card : cards){ 112 | card.onStop(); 113 | } 114 | } 115 | 116 | protected void onFinish(){ 117 | stopActivity(); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/main/java/com/github/pemapmodder/pocketminegui/utils/AsyncTask.java: -------------------------------------------------------------------------------- 1 | package com.github.pemapmodder.pocketminegui.utils; 2 | 3 | /* 4 | * This file is part of PocketMine-GUI. 5 | * 6 | * PocketMine-GUI is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PocketMine-GUI is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with PocketMine-GUI. If not, see . 18 | */ 19 | 20 | import lombok.AccessLevel; 21 | import lombok.Getter; 22 | import lombok.Setter; 23 | 24 | public abstract class AsyncTask extends Thread{ 25 | @Getter @Setter(AccessLevel.PROTECTED) private int progress = 0, max = 0; 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/github/pemapmodder/pocketminegui/utils/GetUrlThread.java: -------------------------------------------------------------------------------- 1 | package com.github.pemapmodder.pocketminegui.utils; 2 | 3 | /* 4 | * This file is part of PocketMine-GUI. 5 | * 6 | * PocketMine-GUI is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PocketMine-GUI is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with PocketMine-GUI. If not, see . 18 | */ 19 | 20 | import java.io.IOException; 21 | import java.io.InputStream; 22 | import java.net.URL; 23 | import java.net.URLConnection; 24 | 25 | public class GetUrlThread extends AsyncTask{ 26 | private final static int STEP = 512; 27 | 28 | private final URL url; 29 | 30 | public byte[] array; 31 | 32 | public GetUrlThread(URL url){ 33 | this.url = url; 34 | } 35 | 36 | @Override 37 | public void run(){ 38 | try{ 39 | URLConnection conn = url.openConnection(); 40 | setMax(conn.getContentLength()); 41 | array = new byte[getMax()]; 42 | try(InputStream is = conn.getInputStream()){ 43 | int progress = 0; 44 | int step = 0; 45 | int pointer = 0; 46 | while(true){ 47 | byte[] buffer = new byte[STEP]; 48 | int read = is.read(buffer); 49 | if(read == -1){ 50 | setProgress(getMax()); 51 | return; 52 | } 53 | System.arraycopy(buffer, 0, array, pointer, read); 54 | pointer += read; 55 | setProgress(progress += STEP); 56 | step++; 57 | } 58 | } 59 | }catch(IOException e){ 60 | e.printStackTrace(); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/com/github/pemapmodder/pocketminegui/utils/NonBlockingANSIReader.java: -------------------------------------------------------------------------------- 1 | package com.github.pemapmodder.pocketminegui.utils; 2 | 3 | /* 4 | * This file is part of PocketMine-GUI. 5 | * 6 | * PocketMine-GUI is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PocketMine-GUI is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with PocketMine-GUI. If not, see . 18 | */ 19 | 20 | import lombok.Getter; 21 | import lombok.RequiredArgsConstructor; 22 | 23 | import java.io.IOException; 24 | import java.io.InputStream; 25 | import java.util.LinkedList; 26 | 27 | @RequiredArgsConstructor 28 | public class NonBlockingANSIReader extends Thread{ 29 | @Getter private final InputStream input; 30 | @Getter private final LinkedList output = new LinkedList<>(); 31 | @Getter private boolean closed = false; 32 | private final StringBuilder buffer = new StringBuilder(); 33 | private EntryType tmpEntryType; 34 | 35 | @Override 36 | public void run(){ 37 | try{ 38 | while(!closed){ 39 | char ch = (char) input.read(); 40 | boolean matched = false; 41 | for(char match : getTerminatingChar()){ 42 | if(match == ch){ 43 | matched = true; 44 | break; 45 | } 46 | } 47 | if(matched){ 48 | if(buffer.length() == 0){ 49 | continue; 50 | } 51 | Entry entry = new Entry(tmpEntryType, buffer.toString()); 52 | synchronized(output){ 53 | output.add(entry); 54 | } 55 | buffer.setLength(0); 56 | continue; 57 | } 58 | buffer.append(ch); 59 | } 60 | }catch(IOException e){ 61 | e.printStackTrace(); 62 | }finally{ 63 | try{ 64 | input.close(); 65 | }catch(IOException e){ 66 | e.printStackTrace(); 67 | } 68 | } 69 | } 70 | 71 | private char[] getTerminatingChar(){ 72 | String title = "\u001b]0;"; 73 | String pmgui = "\u001b]PMGUI;"; 74 | tmpEntryType = EntryType.CONSOLE; 75 | if(buffer.length() >= title.length() && buffer.substring(0, title.length()).equals(title)){ 76 | tmpEntryType = EntryType.TITLE; 77 | return new char[]{'\u0007'}; 78 | }else if(buffer.length() >= pmgui.length() && buffer.substring(0, pmgui.length()).equals(pmgui)){ 79 | tmpEntryType = EntryType.PMGUI; 80 | return new char[]{'\u0007'}; 81 | } 82 | return System.lineSeparator().toCharArray(); 83 | } 84 | 85 | public Entry nextOutput(){ 86 | synchronized(output){ 87 | try{ 88 | return output.remove(0); 89 | }catch(IndexOutOfBoundsException e){ 90 | return null; 91 | } 92 | } 93 | } 94 | 95 | @Getter 96 | public static class Entry{ 97 | private EntryType type; 98 | private String line; 99 | 100 | public Entry(EntryType type, String line){ 101 | if(type == EntryType.TITLE){ 102 | line = line.substring(4); 103 | } 104 | this.type = type; 105 | this.line = line; 106 | } 107 | } 108 | 109 | public enum EntryType{ 110 | CONSOLE, 111 | TITLE, 112 | PMGUI 113 | } 114 | 115 | public void close(){ 116 | closed = true; 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/main/java/com/github/pemapmodder/pocketminegui/utils/NonBlockingBufferedReader.java: -------------------------------------------------------------------------------- 1 | package com.github.pemapmodder.pocketminegui.utils; 2 | 3 | /* 4 | * This file is part of PocketMine-GUI. 5 | * 6 | * PocketMine-GUI is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PocketMine-GUI is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with PocketMine-GUI. If not, see . 18 | */ 19 | 20 | import lombok.RequiredArgsConstructor; 21 | 22 | import java.io.BufferedReader; 23 | import java.io.Closeable; 24 | import java.io.IOException; 25 | import java.util.LinkedList; 26 | import java.util.List; 27 | 28 | @RequiredArgsConstructor 29 | public class NonBlockingBufferedReader extends Thread implements Closeable{ 30 | private final BufferedReader reader; 31 | private final List buffer = new LinkedList<>(); 32 | private boolean closed = false; 33 | 34 | @Override 35 | public void run(){ 36 | while(!closed){ 37 | try{ 38 | String line = reader.readLine(); 39 | if(line != null){ 40 | synchronized(buffer){ 41 | buffer.add(line); 42 | } 43 | } 44 | }catch(IOException e){ 45 | e.printStackTrace(); 46 | } 47 | } 48 | } 49 | 50 | public String readLine(){ 51 | synchronized(buffer){ 52 | try{ 53 | return buffer.remove(0); 54 | }catch(IndexOutOfBoundsException e){ 55 | return null; 56 | } 57 | } 58 | } 59 | 60 | @Override 61 | public void close() throws IOException{ 62 | closed = true; 63 | reader.close(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/com/github/pemapmodder/pocketminegui/utils/Ring.java: -------------------------------------------------------------------------------- 1 | package com.github.pemapmodder.pocketminegui.utils; 2 | 3 | /* 4 | * This file is part of PocketMine-GUI. 5 | * 6 | * PocketMine-GUI is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PocketMine-GUI is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with PocketMine-GUI. If not, see . 18 | */ 19 | 20 | import lombok.Getter; 21 | import org.apache.commons.lang3.ArrayUtils; 22 | 23 | import java.util.Iterator; 24 | 25 | public class Ring implements Iterable{ 26 | private T[] array; 27 | /** 28 | * This is an array offset 29 | */ 30 | private int start = 0; 31 | /** 32 | * This is an internal offset 33 | */ 34 | @Getter private int size = 0; 35 | 36 | public Ring(T[] buffer){ 37 | array = buffer.clone(); 38 | } 39 | 40 | public void add(T t){ 41 | if(size < array.length){ 42 | array[size++] = t; 43 | }else{ 44 | array[start++] = t; 45 | } 46 | } 47 | 48 | public T get(int offset) throws IndexOutOfBoundsException{ 49 | if(offset >= size){ 50 | throw new IndexOutOfBoundsException(); 51 | } 52 | return array[internalOffset(offset)]; 53 | } 54 | 55 | private int internalOffset(int offset){ 56 | return (offset + start) % array.length; 57 | } 58 | 59 | @Override 60 | public Iterator iterator(){ 61 | return new RingIterator(); 62 | } 63 | 64 | private class RingIterator implements Iterator{ 65 | private T[] backup; 66 | private int start; 67 | private int next = 0; 68 | 69 | public RingIterator(){ 70 | assert start == 0 || size == array.length; 71 | backup = ArrayUtils.subarray(array, 0, size); 72 | start = Ring.this.start; 73 | } 74 | 75 | @Override 76 | public boolean hasNext(){ 77 | return next < backup.length; 78 | } 79 | 80 | @Override 81 | public T next(){ 82 | T ret = backup[(next + start) % backup.length]; 83 | next++; // I really want to put it in the same assigument, but then it would become next+++start... 84 | return ret; 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/com/github/pemapmodder/pocketminegui/utils/TerminalCode.java: -------------------------------------------------------------------------------- 1 | package com.github.pemapmodder.pocketminegui.utils; 2 | 3 | /* 4 | * This file is part of PocketMine-GUI. 5 | * 6 | * PocketMine-GUI is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PocketMine-GUI is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with PocketMine-GUI. If not, see . 18 | */ 19 | 20 | import lombok.AllArgsConstructor; 21 | import org.apache.commons.lang3.StringEscapeUtils; 22 | 23 | @AllArgsConstructor 24 | public enum TerminalCode{ 25 | FORMAT_BOLD("\u001b[1m", ""), 26 | FORMAT_ITALIC("\u001b[3m", ""), 27 | FORMAT_UNDERLINE("\u001b[4m", ""), 28 | FORMAT_STRIKETHROUGH("\u001b[9m", ""), 29 | FORMAT_RESET("\u001b[m", ""), 30 | COLOR_BLACK("\u001b[38;5;16m", ""), 31 | COLOR_DARK_BLUE("\u001b[38;5;19m", ""), 32 | COLOR_DARK_GREEN("\u001b[38;5;34m", ""), 33 | COLOR_DARK_AQUA("\u001b[38;5;37m", ""), 34 | COLOR_DARK_RED("\u001b[38;5;124m", ""), 35 | COLOR_PURPLE("\u001b[38;5;127m", ""), 36 | COLOR_GOLD("\u001b[38;5;214m", ""), 37 | COLOR_GRAY("\u001b[38;5;145m", ""), 38 | COLOR_DARK_GRAY("\u001b[38;5;59m", ""), 39 | COLOR_BLUE("\u001b[38;5;63m", ""), 40 | COLOR_GREEN("\u001b[38;5;83m", ""), 41 | COLOR_AQUA("\u001b[38;5;87m", ""), 42 | COLOR_RED("\u001b[38;5;203m", ""), 43 | COLOR_LIGHT_PURPLE("\u001b[38;5;207m", ""), 44 | COLOR_YELLOW("\u001b[38;5;227m", ""), 45 | COLOR_WHITE("\u001b[38;5;231m", ""); 46 | 47 | private String ansi, html; 48 | 49 | private String replace(String src){ 50 | return src.replace(ansi, "" + html); 51 | } 52 | 53 | public static String toHTML(String ansi){ 54 | // for(TerminalCode code : values()){ 55 | // ansi = code.replace(ansi); 56 | // } 57 | // return "" + ansi + ""; 58 | StringBuilder output = new StringBuilder(ansi.length()); 59 | for(int i = 0; i < ansi.length(); ++i){ 60 | if(ansi.charAt(i) == '\u001b'){ 61 | TerminalCode code = startsWithCode(ansi.substring(i)); 62 | if(code != null){ 63 | i += code.ansi.length() // skip the ANSI code 64 | - 1; // to cancel effect of ++i 65 | output.append(code.html); 66 | continue; 67 | } 68 | } 69 | output.append(StringEscapeUtils.escapeHtml4(String.valueOf(ansi.charAt(i)))); 70 | } 71 | return output.toString(); 72 | } 73 | 74 | public static TerminalCode startsWithCode(String ansi){ 75 | for(TerminalCode code : values()){ 76 | if(ansi.startsWith(code.ansi)){ 77 | return code; 78 | } 79 | } 80 | return null; 81 | } 82 | 83 | public static String clean(String ansi){ 84 | for(TerminalCode code : values()){ 85 | ansi = ansi.replace(code.ansi, ""); 86 | } 87 | return ansi; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/main/java/com/github/pemapmodder/pocketminegui/utils/Utils.java: -------------------------------------------------------------------------------- 1 | package com.github.pemapmodder.pocketminegui.utils; 2 | 3 | /* 4 | * This file is part of PocketMine-GUI. 5 | * 6 | * PocketMine-GUI is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PocketMine-GUI is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with PocketMine-GUI. If not, see . 18 | */ 19 | 20 | import org.apache.commons.compress.archivers.tar.TarArchiveEntry; 21 | import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; 22 | import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream; 23 | import org.apache.commons.io.FileUtils; 24 | import org.apache.commons.io.IOUtils; 25 | 26 | import java.io.File; 27 | import java.io.FileOutputStream; 28 | import java.io.IOException; 29 | import java.io.InputStream; 30 | import java.net.URL; 31 | 32 | import static com.github.pemapmodder.pocketminegui.utils.Utils.OperatingSystem.LINUX; 33 | import static com.github.pemapmodder.pocketminegui.utils.Utils.OperatingSystem.MAC; 34 | import static com.github.pemapmodder.pocketminegui.utils.Utils.OperatingSystem.WINDOWS; 35 | 36 | public class Utils{ 37 | private static OperatingSystem os = null; 38 | 39 | public static interface InstallProgressReporter{ 40 | public void report(double fraction); 41 | public void completed(File result); 42 | public void errored(); 43 | } 44 | 45 | public static File installPHP(File home, InstallProgressReporter progress){ 46 | if(getOS() == WINDOWS){ 47 | return installWindowsPHP(home, progress); 48 | }else if(getOS() == MAC){ 49 | return installMacPHP(home, progress); 50 | }else{ 51 | return installLinuxPHP(home, progress); 52 | } 53 | } 54 | 55 | private static File installLinuxPHP(File home, InstallProgressReporter progress){ 56 | progress.report(0.0); 57 | File bin = new File(home, ".pmgui_tmp_pm_linux_installer"); 58 | bin.mkdirs(); 59 | try{ 60 | InputStream get = new URL("http", "get.pocketmine.net", "").openStream(); 61 | Process bash = new ProcessBuilder("bash -s - -v development") 62 | .directory(bin) 63 | .redirectOutput(ProcessBuilder.Redirect.INHERIT) 64 | .redirectError(ProcessBuilder.Redirect.INHERIT) 65 | .start(); 66 | progress.report(0.25); 67 | byte[] bytes = IOUtils.toByteArray(get); 68 | progress.report(0.5); 69 | bash.getOutputStream().write(bytes); 70 | int result = bash.waitFor(); 71 | progress.report(0.75); 72 | if(result == 0){ 73 | File out = new File(bin, "bin"); 74 | FileUtils.copyDirectory(out, new File(home, "bin")); 75 | FileUtils.deleteDirectory(bin); 76 | File output = new File(out, "php7/bin/php"); 77 | progress.completed(output); 78 | return output; 79 | }else{ 80 | FileUtils.deleteDirectory(bin); 81 | return null; 82 | } 83 | }catch(IOException | InterruptedException e){ 84 | e.printStackTrace(); 85 | try{ 86 | FileUtils.deleteDirectory(bin); 87 | }catch(IOException e1){ 88 | } 89 | return null; 90 | } 91 | } 92 | 93 | private static File installMacPHP(File home, InstallProgressReporter progress){ 94 | return installLinuxPHP(home, progress); 95 | } 96 | 97 | private static File installWindowsPHP(File home, InstallProgressReporter progress){ 98 | progress.report(0.0); 99 | try{ 100 | String link = System.getProperty("os.arch").contains("64") ? "https://bintray.com/artifact/download/pocketmine/PocketMine/PHP_7.0.3_x64_Windows.tar.gz" : "https://bintray.com/artifact/download/pocketmine/PocketMine/PHP_7.0.3_x86_Windows.tar.gz"; 101 | URL url = new URL(link); 102 | InputStream gz = url.openStream(); 103 | GzipCompressorInputStream tar = new GzipCompressorInputStream(gz); 104 | TarArchiveInputStream is = new TarArchiveInputStream(tar); 105 | TarArchiveEntry entry; 106 | while((entry = is.getNextTarEntry()) != null){ 107 | if(!entry.isDirectory()){ 108 | String name = entry.getName(); 109 | byte[] buffer = new byte[(int) entry.getSize()]; 110 | IOUtils.read(is, buffer); 111 | File real = new File(home, name); 112 | real.getParentFile().mkdirs(); 113 | IOUtils.write(buffer, new FileOutputStream(real)); 114 | } 115 | } 116 | File output = new File(home, "bin/php/php.exe"); 117 | progress.completed(output); 118 | return output; 119 | }catch(IOException e){ 120 | e.printStackTrace(); 121 | progress.errored(); 122 | return null; 123 | } 124 | } 125 | 126 | public static OperatingSystem getOS(){ 127 | if(os != null){ 128 | return os; 129 | } 130 | String osName = System.getProperty("os.name").toLowerCase(); 131 | if(osName.contains("win")){ 132 | return os = WINDOWS; 133 | } 134 | if(osName.contains("mac")){ 135 | return os = MAC; 136 | } 137 | return os = LINUX; 138 | } 139 | 140 | public static boolean validatePhpBinaries(File phpBinaries){ 141 | String output = exec(phpBinaries.getAbsolutePath(), "-v"); 142 | if(output != null && output.startsWith("PHP ") && output.contains("The PHP Group") && output.contains("(cli)")){ 143 | String version = output.substring(4, output.indexOf(" (cli)")); 144 | output = exec(phpBinaries.getAbsolutePath(), "-r", 145 | "echo (extension_loaded(\"pthreads\") and extension_loaded(\"yaml\")) ? \"ok\" : \"ng\";"); 146 | return "ok".equals(output); 147 | } 148 | return false; 149 | } 150 | 151 | public static String exec(String... cmdLine){ 152 | try{ 153 | Process process = new ProcessBuilder(cmdLine).start(); 154 | process.waitFor(); 155 | return new String(IOUtils.toByteArray(process.getInputStream())); 156 | }catch(IOException | InterruptedException e){ 157 | e.printStackTrace(); 158 | } 159 | return null; 160 | } 161 | 162 | public enum OperatingSystem{ 163 | WINDOWS, 164 | MAC, 165 | LINUX 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /src/main/resources/plugins/adaptor.php: -------------------------------------------------------------------------------- 1 | getServer()->getProperty("pmgui.enabled")) !== 1){ 23 | throw new \RuntimeException("Adaptor plugin must be used with PMGUI only"); 24 | } 25 | } 26 | public function onEnable(){ 27 | $this->getServer()->getPluginManager()->registerEvents($this, $this); 28 | $this->getServer()->getScheduler()->scheduleDelayedTask(new CallbackPluginTask($this, function(){ 29 | new InternalMessage(InternalMessage::SERVER_STARTED, [ 30 | "pluginData" => [ 31 | "version" => $this->getDescription()->getVersion(), 32 | ], 33 | "serverData" => [ 34 | "name" => $this->getServer()->getName(), 35 | "version" => $this->getServer()->getPocketMineVersion(), 36 | "mcpeVersion" => $this->getServer()->getVersion(), 37 | ], 38 | ]); 39 | }), 1); 40 | } 41 | public function onJoin(PlayerJoinEvent $event){ 42 | new InternalMessage(InternalMessage::PLAYER_JOIN, ["name" => $event->getPlayer()->getName()]); 43 | } 44 | public function onQuit(PlayerQuitEvent $event){ 45 | new InternalMessage(InternalMessage::PLAYER_QUIT, ["name" => $event->getPlayer()->getName()]); 46 | } 47 | public function onDisable(){ 48 | new InternalMessage(InternalMessage::PLUGIN_DISABLED); 49 | } 50 | } 51 | 52 | class InternalMessage{ 53 | const SERVER_STARTED = 0; 54 | const PLAYER_JOIN = 1; 55 | const PLAYER_QUIT = 2; 56 | const PLUGIN_DISABLED = 3; 57 | 58 | private $action; 59 | private $payload; 60 | 61 | public function __construct(int $action, $payload, bool $send = true){ 62 | $this->action = $action; 63 | $this->payload = $payload; 64 | if($send){ 65 | $this->send(); 66 | } 67 | } 68 | public function send(){ 69 | $payload = json_encode($this->payload); 70 | echo "\x1b]PMGUI;" . $this->action . ":" . $payload . "\x07"; 71 | } 72 | } 73 | class CallbackPluginTask extends PluginTask{ 74 | private $callable; 75 | 76 | public function __construct(Adaptor $plugin, callable $callable){ 77 | parent::__construct($plugin); 78 | $this->callable = $callable; 79 | } 80 | public function onRun($ticks){ 81 | $c = $this->callable; 82 | $c(); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/resources/pocketmine.yml: -------------------------------------------------------------------------------- 1 | # Main configuration file for PocketMine-MP 2 | # These settings are the ones that cannot be included in server.properties 3 | # Some of these settings are safe, others can break your server if modified incorrectly 4 | # New settings/defaults won't appear automatically on this file when upgrading. 5 | 6 | settings: 7 | #Three-letter language code for server-side localization 8 | #Check your language code on https://en.wikipedia.org/wiki/List_of_ISO_639-2_codes 9 | language: "eng" 10 | #Whether to send all strings translated to server locale or let the device handle them 11 | force-language: false 12 | shutdown-message: "Server closed" 13 | #Allow listing plugins via Query 14 | query-plugins: true 15 | #Show a console message when a plugin uses deprecated API methods 16 | deprecated-verbose: true 17 | #Enable plugin and core profiling by default 18 | enable-profiling: false 19 | #Will only add results when tick measurement is below or equal to given value (default 20) 20 | profile-report-trigger: 20 21 | #Number of AsyncTask workers. 22 | #Used for plugin asynchronous tasks, world generation, compression and web communication. 23 | #Set this approximately to your number of cores. 24 | #If set to auto, it'll try to detect the number of cores (or use 2) 25 | async-workers: auto 26 | 27 | memory: 28 | #Global soft memory limit in megabytes. Set to 0 to disable 29 | #This will trigger low-memory-triggers and fire an event to free memory when the usage goes over this 30 | global-limit: 0 31 | 32 | #Main thread soft memory limit in megabytes. Set to 0 to disable 33 | #This will trigger low-memory-triggers and fire an event to free memory when the usage goes over this 34 | main-limit: 0 35 | 36 | #Main thread hard memory limit in megabytes. Set to 0 to disable 37 | #This will stop the server when the limit is surpassed 38 | main-hard-limit: 1024 39 | 40 | #Period in ticks to check memory (default 1 second) 41 | check-rate: 20 42 | 43 | #Continue firing low-memory-triggers and event while on low memory 44 | continuous-trigger: true 45 | 46 | #Only if memory.continuous-trigger is enabled. Specifies the rate in memory.check-rate steps (default 30 seconds) 47 | continuous-trigger-rate: 30 48 | 49 | garbage-collection: 50 | #Period in ticks to fire the garbage collector manually (default 30 minutes), set to 0 to disable 51 | #This only affect the main thread. Other threads should fire their own collections 52 | period: 36000 53 | 54 | #Fire asynchronous tasks to collect garbage from workers 55 | collect-async-worker: true 56 | 57 | #Trigger on low memory 58 | low-memory-trigger: true 59 | 60 | max-chunks: 61 | #Limit of chunks to load per player, overrides chunk-sending.max-chunks 62 | trigger-limit: 96 63 | 64 | #Do chunk garbage collection on trigger 65 | trigger-chunk-collect: true 66 | 67 | #Trigger on low memory 68 | low-memory-trigger: true 69 | 70 | world-caches: 71 | disable-chunk-cache: true 72 | low-memory-trigger: true 73 | 74 | 75 | network: 76 | #Threshold for batching packets, in bytes. Only these packets will be compressed 77 | #Set to 0 to compress everything, -1 to disable. 78 | batch-threshold: 256 79 | #Compression level used when sending batched packets. Higher = more CPU, less bandwidth usage 80 | compression-level: 7 81 | #Use AsyncTasks for compression. Adds half/one tick delay, less CPU load on main thread 82 | async-compression: false 83 | #Experimental, only for Windows. Tries to use UPnP to automatically port forward 84 | upnp-forwarding: false 85 | 86 | debug: 87 | #If > 1, it will show debug messages in the console 88 | level: 1 89 | #Enables /status, /gc 90 | commands: false 91 | 92 | level-settings: 93 | #The default format that levels will use when created 94 | default-format: mcregion 95 | #If true, converts from a format that is not the default to the default format on load 96 | #NOTE: This is currently not implemented 97 | convert-format: false 98 | #Automatically change levels tick rate to maintain 20 ticks per second 99 | auto-tick-rate: true 100 | auto-tick-rate-limit: 20 101 | #Sets the base tick rate (1 = 20 ticks per second, 2 = 10 ticks per second, etc.) 102 | base-tick-rate: 1 103 | #Tick all players each tick even when other settings disallow this. 104 | always-tick-players: false 105 | 106 | chunk-sending: 107 | #Amount of chunks sent to players per tick 108 | per-tick: 4 109 | #Amount of chunks sent around each player 110 | max-chunks: 192 111 | #Amount of chunks that need to be sent before spawning the player 112 | spawn-threshold: 56 113 | #Save a serialized copy of the chunk in memory for faster sending 114 | #Useful in mostly-static worlds where lots of players join at the same time 115 | cache-chunks: false 116 | 117 | chunk-ticking: 118 | #Max amount of chunks processed each tick 119 | per-tick: 40 120 | #Radius of chunks around a player to tick 121 | tick-radius: 3 122 | light-updates: false 123 | clear-tick-list: true 124 | 125 | chunk-generation: 126 | #Max. amount of chunks in the waiting queue to be generated 127 | queue-size: 8 128 | #Max. amount of chunks in the waiting queue to be populated 129 | population-queue-size: 8 130 | 131 | ticks-per: 132 | animal-spawns: 400 133 | monster-spawns: 1 134 | autosave: 6000 135 | cache-cleanup: 900 136 | 137 | spawn-limits: 138 | monsters: 70 139 | animals: 15 140 | water-animals: 5 141 | ambient: 15 142 | 143 | auto-report: 144 | #Send crash reports for processing 145 | enabled: true 146 | send-code: true 147 | send-settings: true 148 | send-phpinfo: false 149 | host: crash.pocketmine.net 150 | 151 | anonymous-statistics: 152 | #Sends anonymous statistics for data aggregation, plugin usage tracking 153 | enabled: true 154 | host: stats.pocketmine.net 155 | 156 | auto-updater: 157 | enabled: true 158 | on-update: 159 | warn-console: true 160 | warn-ops: true 161 | #Can be development, beta or stable. 162 | preferred-channel: stable 163 | #If using a development version, it will suggest changing the channel 164 | suggest-channels: true 165 | host: www.pocketmine.net 166 | 167 | aliases: 168 | #Examples: 169 | #showtheversion: version 170 | #savestop: [save-all, stop] 171 | 172 | worlds: 173 | #These settings will override the generator set in server.properties and allows loading multiple levels 174 | #Example: 175 | #world: 176 | # seed: 404 177 | # generator: FLAT:2;7,59x1,3x3,2;1;decoration(treecount=80 grasscount=45) 178 | --------------------------------------------------------------------------------