├── .github ├── ISSUE_TEMPLATE │ ├── bug-report.md │ └── suggestion.md └── workflows │ └── maven.yml ├── .gitignore ├── .idea ├── .gitignore ├── compiler.xml ├── discord.xml ├── encodings.xml ├── jarRepositories.xml ├── misc.xml ├── runConfigurations.xml └── vcs.xml ├── AdminTools.iml ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── assets ├── img │ ├── icon-baked.ico │ └── splash_screen.png ├── scripts │ ├── test.atsf │ └── wa.atsf └── themes │ ├── aqua │ ├── consolecolor.txt │ └── style.css │ └── default │ ├── consolecolor.txt │ └── style.css ├── docs ├── Customatisation │ ├── script.md │ └── themes.md ├── index.md ├── mkdocs.yml └── pip.txt ├── pom.xml └── src └── main ├── java └── app │ └── admintools │ ├── AdminTools.java │ ├── AdminToolsLauncher.java │ ├── gui │ ├── HomeWindowController.java │ ├── RconWindowController.java │ ├── SettingsWindowController.java │ ├── StatusWindowController.java │ ├── credentials │ │ ├── credcard │ │ │ └── CredCard.java │ │ └── credwizard │ │ │ └── CredWizard.java │ ├── splash │ │ └── SplashScreen.java │ └── theme │ │ └── ThemeReader.java │ ├── img │ └── unknown_server.png │ ├── querry │ ├── api │ │ └── ApiQuerry.java │ └── mc │ │ ├── MinecraftPing.java │ │ ├── MinecraftPingOptions.java │ │ ├── MinecraftPingReply.java │ │ ├── MinecraftPingUtil.java │ │ └── QuerryUtils.java │ ├── security │ ├── Mozaic.java │ ├── SecureIO.java │ └── credentials │ │ ├── Credentials.java │ │ └── CredentialsIO.java │ ├── textprocessing │ ├── ChatColour.java │ ├── Markup.java │ └── TellrawFormatter.java │ ├── threadmanager │ ├── ThreadManager.java │ └── ThreadType.java │ └── util │ ├── AtLogger.java │ ├── CustomRcon.java │ ├── DRPC.java │ ├── Data.java │ ├── DataType.java │ ├── Utill.java │ ├── Version.java │ └── WindowLoader.java └── resources ├── gui └── fxml │ ├── HomeWindow.fxml │ ├── RconWindow.fxml │ ├── SettingsWindow.fxml │ └── StatusWindow.fxml └── img ├── icon-baked.ico ├── icon.png └── unknown-server.png /.github/ISSUE_TEMPLATE/bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us squish bugs 4 | title: "[BUG]" 5 | labels: '' 6 | assignees: '' 7 | --- 8 | 9 | # **Description** 10 | What happens when the bug occurs? 11 | 12 | # **Reproducing** 13 | Write exactly how to reproduce it. 14 | 15 | # **Log file** 16 | Drag and drop the log file as an atachment. 17 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/suggestion.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Suggest a feature 3 | about: Suggest something you think needs to be in here 4 | title: "[SUGGESTION]" 5 | labels: '' 6 | assignees: '' 7 | --- 8 | 9 | # What you want to have added? 10 | 11 | # How you want to have it be added? 12 | -------------------------------------------------------------------------------- /.github/workflows/maven.yml: -------------------------------------------------------------------------------- 1 | # Build javafx shaded jars for all major platforms 2 | # Builds are stored as artifacts in the action tab 3 | 4 | name: Java CI with Maven 5 | 6 | on: 7 | push: 8 | branches: [ master ] 9 | pull_request: 10 | branches: [ master ] 11 | 12 | jobs: 13 | build-windows: 14 | 15 | runs-on: windows-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | - name: Set up JDK 11 20 | uses: actions/setup-java@v1 21 | with: 22 | java-version: 11 23 | - name: Build with Maven 24 | run: mvn -B package --file pom.xml 25 | 26 | - run: mkdir staging && cp target/admin-tools*.jar staging && cp -r assets staging 27 | - uses: actions/upload-artifact@v1 28 | with: 29 | name: WindowsPackage 30 | path: staging 31 | build-linux: 32 | 33 | runs-on: ubuntu-latest 34 | 35 | steps: 36 | - uses: actions/checkout@v2 37 | - name: Set up JDK 11 38 | uses: actions/setup-java@v1 39 | with: 40 | java-version: 11 41 | - name: Build with Maven 42 | run: mvn -B package --file pom.xml 43 | 44 | - run: mkdir staging && cp target/admin-tools*.jar staging && cp -r assets staging 45 | - uses: actions/upload-artifact@v1 46 | with: 47 | name: LinuxPackage 48 | path: staging 49 | build-macos: 50 | 51 | runs-on: macos-latest 52 | 53 | steps: 54 | - uses: actions/checkout@v2 55 | - name: Set up JDK 11 56 | uses: actions/setup-java@v1 57 | with: 58 | java-version: 11 59 | - name: Build with Maven 60 | run: mvn -B package --file pom.xml 61 | 62 | - run: mkdir staging && cp target/admin-tools*.jar staging && cp -r assets staging 63 | - uses: actions/upload-artifact@v1 64 | with: 65 | name: MacosPackage 66 | path: staging 67 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | credentials.json 2 | admintools.properties 3 | target/** 4 | .idea/** 5 | log/** -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/discord.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /AdminTools.iml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | When contributing follow these guidelines 2 | 3 | ```java 4 | //TODO : add guidelines 5 | ``` 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Java CI with Maven](https://github.com/LukeOnuke/AdminTools/actions/workflows/maven.yml/badge.svg)](https://github.com/LukeOnuke/AdminTools/actions/workflows/maven.yml) 2 | [![ReadTheDocs status](https://img.shields.io/readthedocs/admintools)](https://docs.admintools.app/en/latest/) 3 | [![Downloads](https://img.shields.io/github/downloads/LukeOnuke/admintools/total?color=orange)]() 4 | [![Spiget Rating](https://img.shields.io/spiget/stars/81484?color=orange)](https://www.spigotmc.org/resources/admin-tools.81484/) 5 | [![licence](https://img.shields.io/github/license/lukeonuke/admintools?color=blue)](https://github.com/LukeOnuke/AdminTools/blob/master/LICENSE) 6 | 7 | 8 | # Admin Tools 9 | 10 | ***LEGACY SUPPORT*** 11 | ***For new and better maintained app visit https://admintools.app*** 12 | 13 | The gui rcon administration program for minecraft servers, supporting varius features such as scripting, 14 | custom themes and many more. 15 | 16 | Visit the project website : [https://admintools.app](https://admintools.app) 17 | 18 | Join the community discord : [https://discord.gg/VVuQB868wU](https://discord.gg/VVuQB868wU) 19 | 20 | Docs : [https://docs.admintools.app/en/latest/](https://docs.admintools.app/en/latest/) 21 | 22 | # Setup 23 | 1. Check your java version 24 | - ***java 11 and up is required for this program to run*** 25 | 26 | - Open your terminal (in windows you open it by pressing `Win+R` then typing in ```cmd```) 27 | 28 | - Type in `java -version` 29 | It should return version `11` and up, it looks something like this 30 | ```bash 31 | > C:\Users\virtualuser>java -version 32 | openjdk version "11.0.9" 2020-10-20 33 | OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.9+11) 34 | OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.9+11, mixed mode) 35 | ``` 36 | 2. Download the zip for your operating system 37 | 3. Extract the zip 38 | 4. Run the application 39 | ```java -jar .jar``` 40 | 41 | # Special thanks 42 | - Special thanks to JegKompletson, for creating the new admin tools icon. 43 | - Special thanks to kotyk7 (kotyk), for fixing spelling mistakes and making the messages clear. 44 | --- 45 | 46 | ## Legal info 47 | Icons from [fontsawsome](https://fontawesome.com/), [under the Creative Commons Attribution 4.0 licence](https://fontawesome.com/license). *svg was scaled down* 48 | 49 | LukeOnuke is not affiliated with Mojang Synergies AB. 50 | 51 | "Minecraft" is a trademark of Mojang Synergies AB. 52 | 53 | This program and its code is licensed on the [GNU GPL V3.0 licence](https://github.com/LukeOnuke/AdminTools/blob/master/LICENSE) 54 | -------------------------------------------------------------------------------- /assets/img/icon-baked.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LukeOnuke/AdminTools/0c7fb6b85a304d9966b64568d306b3c8b1afb184/assets/img/icon-baked.ico -------------------------------------------------------------------------------- /assets/img/splash_screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LukeOnuke/AdminTools/0c7fb6b85a304d9966b64568d306b3c8b1afb184/assets/img/splash_screen.png -------------------------------------------------------------------------------- /assets/scripts/test.atsf: -------------------------------------------------------------------------------- 1 | #this is a comment 2 | list 3 | whitelist add arg0 4 | whitelist remove arg0 5 | #this here is a if statement 6 | !if arg0==LukeOnuke whitelist add Luke_oNuke 7 | !print yes yes 8 | !if arg0!=yeet !print yeet -------------------------------------------------------------------------------- /assets/scripts/wa.atsf: -------------------------------------------------------------------------------- 1 | !print §aWhitelist add shortcut §farg0 2 | whitelist add arg0 -------------------------------------------------------------------------------- /assets/themes/aqua/consolecolor.txt: -------------------------------------------------------------------------------- 1 | #303030 -------------------------------------------------------------------------------- /assets/themes/aqua/style.css: -------------------------------------------------------------------------------- 1 | /* 2 | Created on : Jul 7, 2020, 12:13:44 AM 3 | Author : Luka Kresoja 4 | */ 5 | *{ 6 | /*Modify these valiues for creating new themes easly*/ 7 | /* 8 | * ___ _____ _____ _ 9 | * / _ \_ _| |_ _| | 10 | * / /_\ \| | | | | |__ ___ _ __ ___ ___ ___ 11 | * | _ || | | | | '_ \ / _ \ '_ ` _ \ / _ \/ __| 12 | * | | | || | | | | | | | __/ | | | | | __/\__ \ 13 | * \_| |_/\_/ \_/ |_| |_|\___|_| |_| |_|\___||___/ 14 | * 15 | * Aqua theme 16 | * 17 | */ 18 | -at-darkaccent: #002F63; 19 | -at-accent: #0C53A6; 20 | -at-secondaccent: #d7fc03; 21 | -at-lightaccent: #2B6ABC; 22 | -at-background: #424242; 23 | -at-darkbackground: #303030; 24 | -at-lightbackground: #525252; 25 | -at-bordercolor: #5c5c5c; 26 | -at-text: white; 27 | } 28 | 29 | .root{ 30 | -fx-background-color: -at-darkbackground; 31 | -fx-window-color: black; 32 | } 33 | 34 | .rcon{ 35 | -fx-border-color: -at-bordercolor; 36 | } 37 | 38 | .sidePane{ 39 | -fx-background-color: -at-background; 40 | } 41 | 42 | .rconPane{ 43 | -fx-background-color: -at-background; 44 | -fx-border-width: 0px 0px 0px 1px; 45 | } 46 | 47 | .rconTextField{ 48 | -fx-text-box-border: -at-border; 49 | -fx-focus-color: -at-darkaccent; 50 | -fx-faint-focus-color: -at-accent; 51 | -fx-border-color: -at-bordercolor; 52 | -fx-border-radius: 1px; 53 | -fx-control-inner-background: -at-darkbackground; 54 | -fx-background-color: -at-darkbackground; 55 | -fx-prompt-text-fill: derive(-at-text, -30%); 56 | } 57 | 58 | .rconButton{ 59 | -fx-background-color: -at-darkbackground; 60 | -fx-text-fill: -at-text; 61 | -fx-padding: 2px; 62 | -fx-border-color: -at-bordercolor; 63 | -fx-border-width: 1px 64 | } 65 | 66 | .rconButton:hover{ 67 | -fx-background-color: -at-background; 68 | -fx-opacity: 1; 69 | -fx-text-fill: -at-lightbackground; 70 | -fx-padding: 2px; 71 | } 72 | 73 | .text{ 74 | -fx-text-fill: -at-text; 75 | -fx-font-size: 14px; 76 | } 77 | 78 | .title{ 79 | -fx-text-fill: -at-text; 80 | -fx-font-size: 40px; 81 | -fx-fill: white; 82 | } 83 | 84 | .settingsPane{ 85 | -fx-background-color: -at-background; 86 | -fx-border-color: -at-bordercolor; 87 | -fx-border-width: 0px 0px 0px 1px; 88 | } 89 | 90 | .sideMenu{ 91 | -fx-background-color: -at-darkbackground; 92 | -fx-border-color: -at-bordercolor; 93 | -fx-border-width: 0px 1px 0px 0px; 94 | } 95 | 96 | /*Side menu button button - selector for scene*/ 97 | .sideMenuButton{ 98 | -fx-background-color: -at-darkbackground; 99 | -fx-border-color: -at-darkbackground -at-darkbackground -at-darkbackground -at-darkbackground; 100 | -fx-border-width: 0px 2px 1px 1px; 101 | } 102 | 103 | .sideMenuButton .icon{ 104 | -fx-fill: -at-bordercolor; 105 | -fx-max-width: 51.0; 106 | -fx-max-height: 51.0; 107 | } 108 | 109 | .sideMenuButton:selected{ 110 | -fx-background-color: -at-accent; 111 | -fx-border-color: -at-background -at-darkaccent -at-accent -at-background; 112 | -fx-border-width: 0px 2px 1px 0px; 113 | } 114 | 115 | .sideMenuButton:selected .icon{ 116 | -fx-fill: -at-darkaccent; 117 | -fx-max-width: 51.0; 118 | -fx-max-height: 51.0; 119 | } 120 | 121 | .sideMenuButton:disabled{ 122 | -fx-opacity: 1.0; 123 | } 124 | 125 | .sideMenuButton:hover{ 126 | -fx-background-color: -at-background; 127 | -fx-border-color: -at-background -at-lightaccent -at-background -at-background; 128 | -fx-border-width: 0px 2px 1px 1px; 129 | } 130 | 131 | .sideMenuButton:hover .icon{ 132 | -fx-fill: -at-lightaccent; 133 | -fx-max-width: 51.0; 134 | -fx-max-height: 51.0; 135 | } 136 | 137 | /*Scrollbar*/ 138 | .scroll-bar{ 139 | -fx-background-color: -at-darkaccent; 140 | } 141 | 142 | .scroll-bar:horizontal, .scroll-bar:vertical{ 143 | -fx-background-color: -at-background; 144 | } 145 | 146 | .increment-button, .decrement-button { 147 | -fx-background-color: -at-background; 148 | -fx-border-color: -at-bordercolor; 149 | } 150 | 151 | .scroll-bar:horizontal .track, 152 | .scroll-bar:vertical .track{ 153 | -fx-background-color: -at-background; 154 | -fx-border-color: -at-bordercolor; 155 | -fx-background-radius: 0em; 156 | } 157 | 158 | .scroll-bar:horizontal .thumb, 159 | .scroll-bar:vertical .thumb { 160 | -fx-background-color: -at-darkbackground; 161 | -fx-background-radius: 5em; 162 | } 163 | 164 | .scroll-pane > .corner { 165 | -fx-background-color: -at-darkbackground; 166 | } 167 | /*-----------*/ 168 | 169 | .titlePane{ 170 | -fx-background-color: -at-darkaccent; 171 | } 172 | 173 | .borderPane{ 174 | -fx-background-color: -at-background; 175 | -fx-border-color: -at-bordercolor; 176 | -fx-border-width: 1px; 177 | } 178 | 179 | .borderPaneText{ 180 | -fx-text-fill: -at-lightbackground; 181 | -fx-font-size: 13px; 182 | -fx-fill: white; 183 | } 184 | 185 | .labelButton{ 186 | -fx-background-color: -at-background; 187 | -fx-text-fill: white; 188 | -fx-padding: 2px; 189 | -fx-text-fill: -at-text; 190 | -fx-border-color: -at-bordercolor; 191 | -fx-border-width: 1px; 192 | -fx-text-alignment: center; 193 | } 194 | 195 | .labelButton .text{ 196 | -fx-text-alignment: center; 197 | -fx-alignment: center; 198 | -fx-fill: -at-text; 199 | } 200 | 201 | .labelButton:hover{ 202 | -fx-background-color: -at-lightbackground; 203 | -fx-opacity: 1; 204 | -fx-text-fill: -at-bordercolor; 205 | -fx-padding: 2px; 206 | } 207 | 208 | .labelButton:pressed{ 209 | -fx-background-color: -at-darkbackground; 210 | -fx-opacity: 1; 211 | -fx-text-fill: -at-bordercolor; 212 | -fx-padding: 2px; 213 | } 214 | 215 | /*Slider*/ 216 | .slider{ 217 | 218 | } 219 | 220 | .slider .thumb{ 221 | -fx-background-color: -at-darkaccent; 222 | } 223 | 224 | .slider .thumb:active{ 225 | -fx-focus-color: -at-accent; 226 | -fx-faint-focus-color: -at-lightbackground; 227 | } 228 | 229 | .slider .track{ 230 | -fx-background-color: -at-darkbackground; 231 | } 232 | 233 | /*Radio button*/ 234 | .radio-button{ 235 | } 236 | 237 | .radio-button .text{ 238 | -fx-text-fill: -at-text; 239 | -fx-fill: -at-text; 240 | } 241 | 242 | .radio-button .radio{ 243 | -fx-background-color: -at-darkbackground; 244 | } 245 | 246 | .radio-button:selected .radio .dot { 247 | -fx-background-color: -at-darkaccent; 248 | -fx-background-insets: 0; 249 | } 250 | 251 | /*progressbar*/ 252 | 253 | .progress-bar .track{ 254 | -fx-background-color: -at-darkbackground; 255 | } 256 | 257 | .progress-bar:indeterminate .bar{ 258 | -fx-accent: -at-accent; 259 | } 260 | 261 | .progress-bar:determinate .bar{ 262 | -fx-background-color: -at-accent; 263 | } 264 | 265 | /*Status dot*/ 266 | .statusDot{ 267 | -fx-background-radius: 17px; 268 | -fx-background-color: red; 269 | } 270 | 271 | /*List view and its elements*/ 272 | .list-view{ 273 | -fx-background-color: -at-darkbackground; 274 | } 275 | 276 | .list-cell:odd{ 277 | -fx-background-color : -at-lightbackground; 278 | -fx-text-fill: -at-text; 279 | } 280 | 281 | .list-cell:even{ 282 | -fx-background-color : -at-background; 283 | -fx-text-fill: -at-text; 284 | } 285 | 286 | .list-cell:odd{ 287 | -fx-background-color : -at-lightbackground; 288 | -fx-text-fill: -at-text; 289 | } 290 | 291 | .list-cell:even{ 292 | -fx-background-color : -at-background; 293 | -fx-text-fill: -at-text; 294 | } 295 | 296 | .leftSidePane{ 297 | -fx-background-color: -at-background; 298 | -fx-border-color: -at-bordercolor; 299 | -fx-border-width: 0px 1px 0px 0px; 300 | } 301 | 302 | .imageBackground{ 303 | -fx-background-image: url(/app/admintools/img/background.png); 304 | -fx-background-size: cover; 305 | } 306 | 307 | .loginCenter{ 308 | -fx-background-color: -at-background; 309 | -fx-border-color: -at-bordercolor; 310 | -fx-border-width: 1px; 311 | -fx-border-radius: 10px; 312 | -fx-background-radius: 10px; 313 | } 314 | 315 | .pane{ 316 | -fx-background-color: -at-darkbackground; 317 | } 318 | 319 | pane{ 320 | -fx-background-color: -at-darkbackground; 321 | } 322 | 323 | /*choice box*/ 324 | .choice-box{ 325 | -fx-background-color: -at-darkbackground; 326 | } 327 | 328 | .choice-box .label .text{ 329 | -fx-fill: -at-text; 330 | } 331 | 332 | .choice-box .context-menu { 333 | -fx-background-color: -at-darkbackground; 334 | } 335 | .choice-box .menu-item:focused { 336 | -fx-background-color: -at-darkaccent; 337 | } 338 | .choice-box .menu-item > .label { 339 | -fx-text-fill: -at-text; 340 | } 341 | .choice-box .menu-item:focused > .label { 342 | -fx-text-fill: -at-text; 343 | } 344 | 345 | /*Plus*/ 346 | .plus{ 347 | -fx-fill: -at-text; 348 | -fx-font-size: 50px; 349 | } 350 | 351 | .plus:hover{ 352 | -fx-fill: -at-lightaccent; 353 | -fx-font-size: 50px; 354 | } 355 | 356 | .plus:pressed{ 357 | -fx-fill: -at-accent; 358 | -fx-font-size: 50px; 359 | } 360 | 361 | /*Login card, now called credcard*/ 362 | .loginCard{ 363 | -fx-background-color: linear-gradient(to top right, -at-darkaccent 75%, -at-accent 100%); 364 | -fx-margin: 10px; 365 | } 366 | 367 | .loginCard .ctitle{ 368 | -fx-text-fill: -at-text; 369 | } 370 | 371 | .loginCard .ctitle > .text{ 372 | -fx-text-fill: -at-text; 373 | -fx-font-size: 30px; 374 | } 375 | 376 | /*Plus*/ 377 | .edit .plus{ 378 | -fx-fill: -at-text; 379 | -fx-font-size: 50px; 380 | } 381 | 382 | .edit:hover .plus{ 383 | -fx-fill: -at-lightaccent; 384 | -fx-font-size: 50px; 385 | } 386 | 387 | .edit:pressed .plus{ 388 | -fx-fill: -at-accent; 389 | -fx-font-size: 50px; 390 | } 391 | 392 | .splash{ 393 | -fx-background-color: -at-background; 394 | -fx-background-image: url('assets/img/splash_screen.png'); 395 | } -------------------------------------------------------------------------------- /assets/themes/default/consolecolor.txt: -------------------------------------------------------------------------------- 1 | #303030 -------------------------------------------------------------------------------- /assets/themes/default/style.css: -------------------------------------------------------------------------------- 1 | /* 2 | Created on : Jul 7, 2020, 12:13:44 AM 3 | Author : Luka Kresoja 4 | */ 5 | *{ 6 | /*Modify these valiues for creating new themes easly*/ 7 | /* 8 | * ___ _____ _____ _ 9 | * / _ \_ _| |_ _| | 10 | * / /_\ \| | | | | |__ ___ _ __ ___ ___ ___ 11 | * | _ || | | | | '_ \ / _ \ '_ ` _ \ / _ \/ __| 12 | * | | | || | | | | | | | __/ | | | | | __/\__ \ 13 | * \_| |_/\_/ \_/ |_| |_|\___|_| |_| |_|\___||___/ 14 | * 15 | * Default theme 16 | * 17 | */ 18 | -at-darkaccent: #487829; 19 | -at-accent: #699b2c; 20 | -at-secondaccent: #d7fc03; 21 | -at-lightaccent: #b8cf69; 22 | -at-background: #424242; 23 | -at-darkbackground: #303030; 24 | -at-lightbackground: #525252; 25 | -at-bordercolor: #5c5c5c; 26 | -at-text: white; 27 | } 28 | 29 | .root{ 30 | -fx-background-color: -at-darkbackground; 31 | -fx-window-color: black; 32 | } 33 | 34 | .rcon{ 35 | -fx-border-color: -at-bordercolor; 36 | } 37 | 38 | .sidePane{ 39 | -fx-background-color: -at-background; 40 | } 41 | 42 | .rconPane{ 43 | -fx-background-color: -at-background; 44 | -fx-border-width: 0px 0px 0px 1px; 45 | } 46 | 47 | .rconTextField{ 48 | -fx-text-box-border: -at-border; 49 | -fx-focus-color: -at-darkaccent; 50 | -fx-faint-focus-color: -at-accent; 51 | -fx-border-color: -at-bordercolor; 52 | -fx-border-radius: 1px; 53 | -fx-control-inner-background: -at-darkbackground; 54 | -fx-background-color: -at-darkbackground; 55 | -fx-prompt-text-fill: derive(-at-text, -30%); 56 | } 57 | 58 | .rconButton{ 59 | -fx-background-color: -at-darkbackground; 60 | -fx-text-fill: -at-text; 61 | -fx-padding: 2px; 62 | -fx-border-color: -at-bordercolor; 63 | -fx-border-width: 1px 64 | } 65 | 66 | .rconButton:hover{ 67 | -fx-background-color: -at-background; 68 | -fx-opacity: 1; 69 | -fx-text-fill: -at-lightbackground; 70 | -fx-padding: 2px; 71 | } 72 | 73 | .text{ 74 | -fx-text-fill: -at-text; 75 | -fx-font-size: 14px; 76 | } 77 | 78 | .title{ 79 | -fx-text-fill: -at-text; 80 | -fx-font-size: 40px; 81 | -fx-fill: white; 82 | } 83 | 84 | .settingsPane{ 85 | -fx-background-color: -at-background; 86 | -fx-border-color: -at-bordercolor; 87 | -fx-border-width: 0px 0px 0px 1px; 88 | } 89 | 90 | .sideMenu{ 91 | -fx-background-color: -at-darkbackground; 92 | -fx-border-color: -at-bordercolor; 93 | -fx-border-width: 0px 1px 0px 0px; 94 | } 95 | 96 | /*Side menu button button - selector for scene*/ 97 | .sideMenuButton{ 98 | -fx-background-color: -at-darkbackground; 99 | -fx-border-color: -at-darkbackground -at-darkbackground -at-darkbackground -at-darkbackground; 100 | -fx-border-width: 0px 2px 1px 1px; 101 | } 102 | 103 | .sideMenuButton .icon{ 104 | -fx-fill: -at-bordercolor; 105 | -fx-max-width: 51.0; 106 | -fx-max-height: 51.0; 107 | } 108 | 109 | .sideMenuButton:selected{ 110 | -fx-background-color: -at-accent; 111 | -fx-border-color: -at-background -at-darkaccent -at-accent -at-background; 112 | -fx-border-width: 0px 2px 1px 0px; 113 | } 114 | 115 | .sideMenuButton:selected .icon{ 116 | -fx-fill: -at-darkaccent; 117 | -fx-max-width: 51.0; 118 | -fx-max-height: 51.0; 119 | } 120 | 121 | .sideMenuButton:disabled{ 122 | -fx-opacity: 1.0; 123 | } 124 | 125 | .sideMenuButton:hover{ 126 | -fx-background-color: -at-background; 127 | -fx-border-color: -at-background -at-lightaccent -at-background -at-background; 128 | -fx-border-width: 0px 2px 1px 1px; 129 | } 130 | 131 | .sideMenuButton:hover .icon{ 132 | -fx-fill: -at-lightaccent; 133 | -fx-max-width: 51.0; 134 | -fx-max-height: 51.0; 135 | } 136 | 137 | /*Scrollbar*/ 138 | .scroll-bar{ 139 | -fx-background-color: -at-darkaccent; 140 | } 141 | 142 | .scroll-bar:horizontal, .scroll-bar:vertical{ 143 | -fx-background-color: -at-background; 144 | } 145 | 146 | .increment-button, .decrement-button { 147 | -fx-background-color: -at-background; 148 | -fx-border-color: -at-bordercolor; 149 | } 150 | 151 | .scroll-bar:horizontal .track, 152 | .scroll-bar:vertical .track{ 153 | -fx-background-color: -at-background; 154 | -fx-border-color: -at-bordercolor; 155 | -fx-background-radius: 0em; 156 | } 157 | 158 | .scroll-bar:horizontal .thumb, 159 | .scroll-bar:vertical .thumb { 160 | -fx-background-color: -at-darkbackground; 161 | -fx-background-radius: 5em; 162 | } 163 | 164 | .scroll-pane > .corner { 165 | -fx-background-color: -at-darkbackground; 166 | } 167 | /*-----------*/ 168 | 169 | .titlePane{ 170 | -fx-background-color: -at-darkaccent; 171 | } 172 | 173 | .borderPane{ 174 | -fx-background-color: -at-background; 175 | -fx-border-color: -at-bordercolor; 176 | -fx-border-width: 1px; 177 | } 178 | 179 | .borderPaneText{ 180 | -fx-text-fill: -at-lightbackground; 181 | -fx-font-size: 13px; 182 | -fx-fill: white; 183 | } 184 | 185 | .labelButton{ 186 | -fx-background-color: -at-background; 187 | -fx-text-fill: white; 188 | -fx-padding: 2px; 189 | -fx-text-fill: -at-text; 190 | -fx-border-color: -at-bordercolor; 191 | -fx-border-width: 1px; 192 | -fx-text-alignment: center; 193 | } 194 | 195 | .labelButton .text{ 196 | -fx-text-alignment: center; 197 | -fx-alignment: center; 198 | -fx-fill: -at-text; 199 | } 200 | 201 | .labelButton:hover{ 202 | -fx-background-color: -at-lightbackground; 203 | -fx-opacity: 1; 204 | -fx-text-fill: -at-bordercolor; 205 | -fx-padding: 2px; 206 | } 207 | 208 | .labelButton:pressed{ 209 | -fx-background-color: -at-darkbackground; 210 | -fx-opacity: 1; 211 | -fx-text-fill: -at-bordercolor; 212 | -fx-padding: 2px; 213 | } 214 | 215 | /*Slider*/ 216 | .slider{ 217 | 218 | } 219 | 220 | .slider .thumb{ 221 | -fx-background-color: -at-darkaccent; 222 | } 223 | 224 | .slider .thumb:active{ 225 | -fx-focus-color: -at-accent; 226 | -fx-faint-focus-color: -at-lightbackground; 227 | } 228 | 229 | .slider .track{ 230 | -fx-background-color: -at-darkbackground; 231 | } 232 | 233 | /*Radio button*/ 234 | .radio-button{ 235 | } 236 | 237 | .radio-button .text{ 238 | -fx-text-fill: -at-text; 239 | -fx-fill: -at-text; 240 | } 241 | 242 | .radio-button .radio{ 243 | -fx-background-color: -at-darkbackground; 244 | } 245 | 246 | .radio-button:selected .radio .dot { 247 | -fx-background-color: -at-darkaccent; 248 | -fx-background-insets: 0; 249 | } 250 | 251 | /*progressbar*/ 252 | 253 | .progress-bar .track{ 254 | -fx-background-color: -at-darkbackground; 255 | } 256 | 257 | .progress-bar:indeterminate .bar{ 258 | -fx-accent: -at-accent; 259 | } 260 | 261 | .progress-bar:determinate .bar{ 262 | -fx-background-color: -at-accent; 263 | } 264 | 265 | /*Status dot*/ 266 | .statusDot{ 267 | -fx-background-radius: 17px; 268 | -fx-background-color: red; 269 | } 270 | 271 | /*List view and its elements*/ 272 | .list-view{ 273 | -fx-background-color: -at-darkbackground; 274 | } 275 | 276 | .list-cell:odd{ 277 | -fx-background-color : -at-lightbackground; 278 | -fx-text-fill: -at-text; 279 | } 280 | 281 | .list-cell:even{ 282 | -fx-background-color : -at-background; 283 | -fx-text-fill: -at-text; 284 | } 285 | 286 | .list-cell:odd{ 287 | -fx-background-color : -at-lightbackground; 288 | -fx-text-fill: -at-text; 289 | } 290 | 291 | .list-cell:even{ 292 | -fx-background-color : -at-background; 293 | -fx-text-fill: -at-text; 294 | } 295 | 296 | .leftSidePane{ 297 | -fx-background-color: -at-background; 298 | -fx-border-color: -at-bordercolor; 299 | -fx-border-width: 0px 1px 0px 0px; 300 | } 301 | 302 | .imageBackground{ 303 | -fx-background-image: url(/app/admintools/img/background.png); 304 | -fx-background-size: cover; 305 | } 306 | 307 | .loginCenter{ 308 | -fx-background-color: -at-background; 309 | -fx-border-color: -at-bordercolor; 310 | -fx-border-width: 1px; 311 | -fx-border-radius: 10px; 312 | -fx-background-radius: 10px; 313 | } 314 | 315 | .pane{ 316 | -fx-background-color: -at-darkbackground; 317 | } 318 | 319 | pane{ 320 | -fx-background-color: -at-darkbackground; 321 | } 322 | 323 | /*choice box*/ 324 | .choice-box{ 325 | -fx-background-color: -at-darkbackground; 326 | } 327 | 328 | .choice-box .label .text{ 329 | -fx-fill: -at-text; 330 | } 331 | 332 | .choice-box .context-menu { 333 | -fx-background-color: -at-darkbackground; 334 | } 335 | .choice-box .menu-item:focused { 336 | -fx-background-color: -at-darkaccent; 337 | } 338 | .choice-box .menu-item > .label { 339 | -fx-text-fill: -at-text; 340 | } 341 | .choice-box .menu-item:focused > .label { 342 | -fx-text-fill: -at-text; 343 | } 344 | 345 | /*Plus*/ 346 | .plus{ 347 | -fx-fill: -at-text; 348 | -fx-font-size: 50px; 349 | } 350 | 351 | .plus:hover{ 352 | -fx-fill: -at-lightaccent; 353 | -fx-font-size: 50px; 354 | } 355 | 356 | .plus:pressed{ 357 | -fx-fill: -at-accent; 358 | -fx-font-size: 50px; 359 | } 360 | 361 | /*Login card, now called credcard*/ 362 | .loginCard{ 363 | -fx-opacity: 1; 364 | -fx-background-color: linear-gradient(to top right, -at-darkaccent 75%, -at-accent 100%); 365 | -fx-margin: 10px; 366 | } 367 | 368 | .loginCard .ctitle{ 369 | -fx-text-fill: -at-text; 370 | } 371 | 372 | .loginCard .ctitle > .text{ 373 | -fx-text-fill: -at-text; 374 | -fx-font-size: 30px; 375 | } 376 | 377 | /*Plus*/ 378 | .edit .plus{ 379 | -fx-fill: -at-text; 380 | -fx-font-size: 50px; 381 | } 382 | 383 | .edit:hover .plus{ 384 | -fx-fill: -at-lightaccent; 385 | -fx-font-size: 50px; 386 | } 387 | 388 | .edit:pressed .plus{ 389 | -fx-fill: -at-accent; 390 | -fx-font-size: 50px; 391 | } 392 | 393 | .splash{ 394 | -fx-background-color: -at-darkbackground; 395 | -fx-background-image: url("/assets/img/splash_screen.png"); 396 | -fx-background-position: center center; 397 | -fx-background-size: cover; 398 | } 399 | 400 | .transparent{ 401 | -fx-opacity: 0; 402 | } 403 | 404 | .transparent:child{ 405 | -fx-opacity: 1; 406 | } 407 | 408 | .logo{ 409 | -fx-fill: -at-bordercolor; 410 | } -------------------------------------------------------------------------------- /docs/Customatisation/script.md: -------------------------------------------------------------------------------- 1 | # Scripting 2 | AdminTools uses Admin Tools Script for its scripting. 3 | *Added in version 6.0.0` 4 | 5 | Call them with `@fileNameWithoutTheExtention` 6 | 7 | **Example :** 8 | File named wa.atsf , you call it with just @wa [args] 9 | 10 | Situated in the `/Assets/scripts/` folder 11 | 12 | File ends with `.atsf` and **can not contain** any dots or mc formatting codes. 13 | 14 | Example of valid names : 15 | - `serverShutdown.atsf` 16 | - `script1.atsf` 17 | - `goodScript.atsf` 18 | 19 | Examples of invalid names: 20 | 21 | - `yeet.me.atsf` 22 | - `§cinvalid§9name§f.atsf` 23 | 24 | 25 | It is recomended by the atsf file convention to name your scripts with big letters to seperate words. 26 | 27 | ## ATSF file convention 28 | 29 | The convention specifying naming and contents of `atsf` files 30 | 31 | ### Naming 32 | File ends with `.atsf` and **can not contain** any dots , mc formatting codes or spaces 33 | 34 | `.atsf` stands for Admin Tools Script File. 35 | 36 | Example of valid names : 37 | - `serverShutdown.atsf` 38 | - `script1.atsf` 39 | - `goodScript.atsf` 40 | 41 | Examples of invalid names: 42 | 43 | - `yeet.me.atsf` 44 | - `§cinvalid§9name§f.atsf` 45 | 46 | Words are separated by big letters (cammel case). 47 | 48 | Example : `validName.atsf` 49 | ### Function and commands 50 | Commands are seperated by newline characters. 51 | 52 | Comments start with `#` 53 | ```atsf 54 | # This is a comment 55 | #This is too a comment, but looks less nice 56 | ``` 57 | 58 | You cant call a script (function) from another function. 59 | 60 | ### Arguments 61 | Arguments get parsed from the arguments you give in the call to the script. 62 | 63 | So `@example [arg0] [arg1] [arg2] [arg3] [arg4] [arg5]` and so on 64 | 65 | In the file you can mention the arguments with a `argN` constant. 66 | 67 | **Example : ** 68 | ```atsf 69 | # Example of arguments 70 | !print arg0 arg3 71 | ``` 72 | 73 | If a argument is not provided it will just stay in the argN form. 74 | 75 | # Commands 76 | All the commands used in the console can be used here. 77 | 78 | Although some commands were added for the sole purpuse of being used in scripts. 79 | 80 | ## IF (LOGIC COMMAND) 81 | Logic commands are commands used for logic. 82 | 83 | The usual if statement. 84 | 85 | **Syntax** : 86 | ``` 87 | !if [logic] [command] 88 | ``` 89 | 90 | **Examples :** 91 | ```atsf 92 | !if arg0==Server_Shutdown kick @a Server maintenence 93 | 94 | !if arg2!=add kick arg1 95 | ``` 96 | 97 | **Logic :** 98 | 99 | Consists of two operators **==** *(equal)* and **!=** *(is not equal)*. 100 | 101 | **⚠⚠⚠ The check cant have spaces**, `arg1!=yeet me` **wont work!** 102 | 103 | ## PRINT 104 | Prints out what it has been given. Supports color. 105 | 106 | Syntax : 107 | ```atsf 108 | !print [text] 109 | ``` 110 | 111 | Example ; 112 | ```atsf 113 | !print Batch job done 114 | ``` 115 | Since print supports color, you can print colored text to the console. Using bukkit highlight. 116 | [Usefull tool for creating colored messages : https://www.thomasvdbulk.nl/minecraft/](https://www.thomasvdbulk.nl/minecraft/) 117 | ```atsf 118 | !print §aAdded §barg0 §ato the whitelist 119 | ``` 120 | 121 | # Example 122 | ```atsf 123 | # Kick all the players with a specified message 124 | 125 | # Kick them with default message 126 | !if arg0==e kick @a Server maintenence 127 | 128 | # Kick them with more elaborate message 129 | !if arg0!=e kick @a arg0 130 | ``` -------------------------------------------------------------------------------- /docs/Customatisation/themes.md: -------------------------------------------------------------------------------- 1 | # Themes 2 | Themes were added in `v5.0.0` 3 | 4 | Theme file structure 5 | ``` 6 | ThemeMainFolder 7 | | 8 | |--- style.css 9 | |--- consolecolor.txt 10 | ``` 11 | 12 | ## Creating a theme 13 | You can create themes by copying the default theme and pasting it into the `/Assets/Themes/` folder. 14 | 15 | After copy pasting the default theme rename it to what you want. 16 | !!! WARNING Themes can not contain spaces in their file name, otherwise the theme wont work. 17 | 18 | Then change the given valiues in the css to easly create a theme. This part : 19 | 20 | ```css 21 | *{ 22 | /*Modify these valiues for creating new themes easly*/ 23 | /* 24 | * ___ _____ _____ _ 25 | * / _ \_ _| |_ _| | 26 | * / /_\ \| | | | | |__ ___ _ __ ___ ___ ___ 27 | * | _ || | | | | '_ \ / _ \ '_ ` _ \ / _ \/ __| 28 | * | | | || | | | | | | | __/ | | | | | __/\__ \ 29 | * \_| |_/\_/ \_/ |_| |_|\___|_| |_| |_|\___||___/ 30 | * 31 | * Default theme 32 | * 33 | */ 34 | -at-darkaccent: #487829; 35 | -at-accent: #699b2c; 36 | -at-secondaccent: #d7fc03; 37 | -at-lightaccent: #b8cf69; 38 | -at-background: #424242; 39 | -at-darkbackground: #303030; 40 | -at-lightbackground: #525252; 41 | -at-bordercolor: #5c5c5c; 42 | -at-text: white; 43 | } 44 | 45 | ``` 46 | Change the "Default theme" to The name of your theme. 47 | 48 | Now you can change the color valiues. 49 | 50 | If you need to change the color hex valiue in `consolecolor.txt` 51 | 52 | You can also change the other parts of the css. If you create a theme and publish it, add it to the theme list. 53 | 54 | ## Theme list 55 | |Theme name| Theme author | Theme github link | Bundled in latest version? | 56 | |--|--|--|--| 57 | | Default | LukeOnuke | [link](https://github.com/LukeOnuke/AdminTools/tree/master/AdminTools/Assets/Themes/Default) | yes | 58 | | Aqua | LukeOnuke | [link](https://github.com/LukeOnuke/AdminTools/tree/master/AdminTools/Assets/Themes/Aqua) | yes | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | # Admin tools 2 | [![daym](https://img.shields.io/github/downloads/LukeOnuke/AdminTools/total)](https://github.com/LukeOnuke/AdminTools/releases) [![Spiget Downloads](https://img.shields.io/spiget/downloads/81484?label=spigot%20downloads)](https://www.spigotmc.org/resources/admin-tools.81484/) ![wow here](https://img.shields.io/github/license/LukeOnuke/AdminTools) ![wow](https://img.shields.io/github/v/release/LukeOnuke/AdminTools?include_prereleases) [![Documentation Status](https://readthedocs.org/projects/admintools/badge/?version=latest)](https://docs.admintools.app/en/latest/?badge=latest) 3 | 4 | AdminTools is a administration program for minecraft servers. 5 | > Use the **sidebar** and **navbar** to navigate through the docs. 6 | 7 | Github : [https://github.com/LukeOnuke/AdminTools](https://github.com/LukeOnuke/AdminTools) 8 | 9 | Website : [https://admintools.app](https://admintools.app) 10 | 11 | Spigot : [https://www.spigotmc.org/threads/admin-tools.451976/](https://www.spigotmc.org/threads/admin-tools.451976/) 12 | 13 | 14 | ## Legal 15 | Icons from [fontsawsome](https://fontawesome.com/), [under the Creative Commons Attribution 4.0 licence](https://fontawesome.com/license). *svg was scaled down* 16 | This program is licensed under the **GPL-V3 license** 17 | LukeOnuke (the author of this program) and all the contributers aren't asociated with Mojang Synergies AB 18 | Some images contained in the program either contain parts of images copyrighted by Mojang Synergies AB or they are copyrighted by Mojang Synergies AB 19 | For more info read the **legal** section of the `readme.md` file in the github repository 20 | 21 | # Installation 22 | Steps for installing the program 23 | 24 | ## Basic instalation 25 | 1. Download the zip file from the [Github releases](https://github.com/LukeOnuke/AdminTools/releases/latest) 26 | 2. Place it in the folder of your choice 27 | **Protip:** Remember that folder 28 | 3. Extract the contents of the zip file into that folder 29 | 4. Execute the program file (**AdminTools.jar**) 30 | 31 | ## Advanced instalation 32 | Follow the steps from the basic instalation 33 | 34 | **Setting up the program so that in appears in search** 35 | If you are on **windows** : 36 | 37 | 1. Go to `%appdata%\Microsoft\Windows\Start Menu\Programs` 38 | 2. Create a new directory called `AdminTools` 39 | 3. Open the directory 40 | 4. Place a shortcut to the *program file*(**AdminTools.jar**) 41 | 42 | ## Snapshots and artifacts 43 | Snapshots are provided when there are big changes to the program itself, **keep in mind that they are development builds**. 44 | 45 | Artifacts can be gotten from the action tab of github, in the overview section. 46 | # Settings 47 | -------------------------------------------------------------------------------- /docs/mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: AdminTools 2 | theme: 3 | name: slate 4 | nav_style: dark 5 | markdown_extensions: 6 | - toc: 7 | permalink: # 8 | - tables 9 | - admonition 10 | - def_list 11 | - footnotes 12 | - mdx_gh_links: 13 | user: LukeOnuke 14 | repo: AdminTools -------------------------------------------------------------------------------- /docs/pip.txt: -------------------------------------------------------------------------------- 1 | mkdocs-bootswatch -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | app.admintools 8 | admin-tools 9 | 7.0.0 10 | 11 | 12 | 13 | 11 14 | 11 15 | UTF-8 16 | app.admintools.AdminTools 17 | app.admintools.AdminTools 18 | 19 | 20 | 21 | 22 | org.apache.maven.plugins 23 | maven-compiler-plugin 24 | 3.8.1 25 | 26 | 27 | org.sonatype.sisu 28 | sisu-guice 29 | 30 | 31 | org.apache.maven 32 | maven-model-builder 33 | 34 | 35 | org.apache.maven 36 | maven-artifact 37 | 38 | 39 | org.sonatype.sisu 40 | sisu-inject-bean 41 | 42 | 43 | org.apache.maven 44 | maven-plugin-api 45 | 46 | 47 | org.apache.maven 48 | maven-repository-metadata 49 | 50 | 51 | org.apache.maven 52 | * 53 | 54 | 55 | 56 | 57 | 58 | 59 | org.openjfx 60 | javafx-maven-plugin 61 | 0.0.5 62 | 63 | 64 | org.apache.maven.plugin-tools 65 | maven-plugin-tools 66 | 67 | 68 | org.apache.maven 69 | maven-artifact 70 | 71 | 72 | org.sonatype.sisu 73 | sisu-inject-bean 74 | 75 | 76 | org.sonatype.sisu 77 | * 78 | 79 | 80 | org.apache.maven 81 | maven-plugin-api 82 | 83 | 84 | org.codehaus.plexus 85 | plexus-io 86 | 87 | 88 | org.apache.maven 89 | maven-plugin 90 | 91 | 92 | javax.annotation 93 | jsr250-api 94 | 95 | 96 | org.apache.maven 97 | maven-model 98 | 99 | 100 | org.apache.maven 101 | maven-core 102 | 103 | 104 | 105 | 106 | 107 | org.openjfx 108 | javafx-controls 109 | 15.0.1 110 | 111 | 112 | 113 | 114 | org.openjfx 115 | javafx-media 116 | 15.0.1 117 | 118 | 119 | 120 | 121 | org.openjfx 122 | javafx-base 123 | 15.0.1 124 | 125 | 126 | 127 | 128 | org.openjfx 129 | javafx-fxml 130 | 15.0.1 131 | 132 | 133 | 134 | 135 | org.openjfx 136 | javafx-graphics 137 | 15.0.1 138 | 139 | 140 | 141 | 142 | org.openjfx 143 | javafx-web 144 | 15.0.1 145 | 146 | 147 | 148 | 149 | com.google.code.gson 150 | gson 151 | 2.9.0 152 | 153 | 154 | 155 | com.github.LukeOnuke 156 | SimpleFxDialog 157 | v2.2.0 158 | 159 | 160 | 161 | com.github.Vatuu 162 | discord-rpc 163 | 1.6.2 164 | 165 | 166 | 167 | org.apache.commons 168 | commons-lang3 169 | 3.8.1 170 | 171 | 172 | 173 | com.github.Pequla 174 | RconCore 175 | v1.2 176 | 177 | 178 | 179 | 180 | 181 | 182 | jitpack.io 183 | https://jitpack.io 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | org.apache.maven.plugins 192 | maven-jar-plugin 193 | 3.2.0 194 | 195 | 196 | 197 | true 198 | lib 199 | app.admintools.AdminTools 200 | true 201 | 202 | 203 | assets/img/splash_screen.png 204 | 205 | 206 | 207 | 208 | 209 | org.openjfx 210 | javafx-maven-plugin 211 | 0.0.5 212 | 213 | app.admintools.AdminTools 214 | 215 | 216 | 217 | org.apache.maven.plugins 218 | maven-assembly-plugin 219 | 220 | 221 | jar-with-dependencies 222 | 223 | 224 | 225 | 226 | app.admintools.AdminTools 227 | true 228 | 229 | 230 | 231 | 232 | 233 | org.apache.maven.plugins 234 | maven-shade-plugin 235 | 3.2.3 236 | 237 | 238 | package 239 | 240 | shade 241 | 242 | 243 | false 244 | 245 | 246 | 247 | 248 | 249 | 250 | -------------------------------------------------------------------------------- /src/main/java/app/admintools/AdminTools.java: -------------------------------------------------------------------------------- 1 | package app.admintools; 2 | 3 | import app.admintools.util.AtLogger; 4 | import app.admintools.util.Data; 5 | import app.admintools.util.Version; 6 | 7 | import java.io.File; 8 | import java.io.IOException; 9 | import java.text.SimpleDateFormat; 10 | import java.util.Date; 11 | import java.util.logging.FileHandler; 12 | import java.util.logging.SimpleFormatter; 13 | 14 | /* 15 | * Image credits 16 | * "Gear Icon made by Freepik from www.flaticon.com" 17 | * 18 | */ 19 | 20 | /** 21 | * AdminTools , cool ascii art got messed up 22 | * 23 | * Admintools by lukeonuke 24 | */ 25 | public class AdminTools { 26 | /** 27 | * @param args the command line arguments 28 | */ 29 | public static void main(String[] args) { 30 | Data.arguments = args; 31 | AtLogger.init(); //Initilise at logger 32 | 33 | //Log writer 34 | FileHandler fh; //Create writer 35 | File pathToLogDir = new File("log/"); //Path to log dir 36 | try { 37 | //See if the log exists 38 | if(!pathToLogDir.exists()){ 39 | pathToLogDir.mkdir(); 40 | } 41 | // This block configure the logger with handler and formatter 42 | //File name for log file 43 | String fileName = new SimpleDateFormat("dd-MM-yyyy-@hh-mm-ss").format(new Date()); 44 | fileName = "log-" + fileName + ".log"; 45 | //Initilise the file handeler 46 | fh = new FileHandler("log/" + fileName); 47 | AtLogger.logger.addHandler(fh); 48 | //Formatter for the logger 49 | SimpleFormatter formatter = new SimpleFormatter(); 50 | fh.setFormatter(formatter); 51 | 52 | // the following statement is used to log initialsation 53 | AtLogger.logger.info("Initilising"); 54 | 55 | } catch (SecurityException | IOException e) { 56 | System.err.println("Error in startup"); 57 | } 58 | 59 | Version ver = Version.getInstance(); 60 | if(ver.isDevelopmentVersion()){ 61 | AtLogger.logger.info("Is development version, snapshot " + ver.getSnapshotVersion()); 62 | } 63 | 64 | AtLogger.logger.info("\nAdminTools version : " + ver.getStrippedVersion() + "\n\tAs int : " + ver.getVersionAsInt(ver.getFullVersionNumber()) + "\n\tAs full : " + ver.getFullVersionNumber()+ "\n\tSnapshot: " +ver.getSnapshotVersion()); 65 | AdminToolsLauncher.launchAdminTools(args); 66 | System.exit(0); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/app/admintools/AdminToolsLauncher.java: -------------------------------------------------------------------------------- 1 | package app.admintools; 2 | 3 | import app.admintools.gui.splash.SplashScreen; 4 | import app.admintools.textprocessing.TellrawFormatter; 5 | import app.admintools.util.*; 6 | import com.google.gson.Gson; 7 | import com.google.gson.JsonObject; 8 | import com.lukeonuke.simplefxdialog.Dialog; 9 | import com.lukeonuke.simplefxdialog.img.DialogImage; 10 | import javafx.application.Application; 11 | import javafx.application.Platform; 12 | import javafx.fxml.FXMLLoader; 13 | import javafx.scene.Parent; 14 | import javafx.scene.Scene; 15 | import javafx.scene.image.Image; 16 | import javafx.stage.Stage; 17 | import javafx.stage.StageStyle; 18 | import net.arikia.dev.drpc.DiscordRPC; 19 | import net.kronos.rkon.core.ex.AuthenticationException; 20 | 21 | import java.io.File; 22 | import java.io.IOException; 23 | import java.text.SimpleDateFormat; 24 | import java.util.Date; 25 | import java.util.logging.FileHandler; 26 | import java.util.logging.SimpleFormatter; 27 | 28 | /** 29 | * Launches the admintools application 30 | */ 31 | public class AdminToolsLauncher extends Application { 32 | @Override 33 | public void start(Stage stage) throws Exception { 34 | Data d = Data.getInstance(); 35 | 36 | Parent root; 37 | 38 | //Load homepage 39 | root = FXMLLoader.load(getClass().getResource("/gui/fxml/HomeWindow.fxml")); 40 | 41 | //Set selected theme css 42 | Utill.setSelectedTheme(root); 43 | 44 | Scene scene = new Scene(root); 45 | 46 | stage.setScene(scene); 47 | 48 | stage.setOnCloseRequest((event) -> { 49 | Thread closer = new Thread(() -> { 50 | AtLogger.logger.info("Closing"); 51 | //magic 52 | Platform.runLater(stage::hide); 53 | 54 | try { 55 | CustomRcon cr = CustomRcon.getInstance(); 56 | if (d.getMessageNotify()) { 57 | cr.command(TellrawFormatter.assembleLogoutTellraw(d.getMessageUsername())); 58 | } 59 | cr.disconnect(); 60 | AtLogger.logger.info( "Successfully disconnected"); 61 | } catch (IOException | AuthenticationException ex) { 62 | AtLogger.logger.warning(AtLogger.formatException(ex)); 63 | } catch (NullPointerException ex) { 64 | //Its normal for it to trow a null pointer exception on exit if no connection is avalable 65 | } 66 | DiscordRPC.discordShutdown(); 67 | AtLogger.logger.info( "Shutdown discordRPC"); 68 | Platform.exit(); 69 | System.exit(0); 70 | }, "CloserThread"); 71 | closer.start(); 72 | }); 73 | 74 | //title 75 | stage.setTitle("Admin Tools"); 76 | //Setting the icon 77 | stage.getIcons().add(new Image(AdminTools.class.getResourceAsStream(Utill.getPath("/img/icon.png")))); 78 | 79 | 80 | 81 | Stage splash = new Stage(StageStyle.TRANSPARENT); 82 | splash.setScene(new Scene(new SplashScreen(), -1.0, -1.0, true)); 83 | splash.getIcons().add(new Image(AdminToolsLauncher.class.getResourceAsStream(Utill.getPath("/img/icon.png")))); 84 | splash.show(); 85 | Thread splashThread = new Thread(() -> { 86 | try{ 87 | //Discord 88 | AtLogger.logger.info( "Connecting to discord"); 89 | DRPC.initialise(); 90 | AtLogger.logger.info("Connected to discord"); 91 | 92 | //AVCS 93 | Thread vChecker = new Thread(() -> { 94 | //Write if new version avalable 95 | AtLogger.logger.info("Checking for new verison"); 96 | 97 | JsonObject updateStats; 98 | try { 99 | updateStats = new Gson().fromJson(Utill.getHTTPRequest("https://api.github.com/repos/LukeOnuke/AdminTools/releases/latest"), JsonObject.class); 100 | if (!updateStats.get("draft").getAsBoolean()) { 101 | if (Version.getVersionAsInt(updateStats.get("tag_name").getAsString()) > Version.getVersionAsInt(("v" + Version.getInstance().getFullVersionNumber()))) { 102 | Platform.runLater(() -> { 103 | Dialog.okDialog(DialogImage.INFO_EXCLAMATION, "New version available!", "New version found " + updateStats.get("tag_name").getAsString() + "\n" + updateStats.get("name").getAsString() + "\nGet it from github : https://get.admintools.app"); 104 | }); 105 | } 106 | } 107 | AtLogger.logger.info("Check complete"); 108 | } catch (IOException ex) { 109 | AtLogger.logger.warning(AtLogger.formatException(ex)); 110 | } 111 | 112 | }, "Autonomous version control"); 113 | vChecker.start(); 114 | 115 | Thread.sleep(2000); 116 | } catch (InterruptedException ie) { 117 | AtLogger.logger.warning(AtLogger.formatException(ie)); 118 | } 119 | Platform.runLater(() -> { 120 | splash.hide(); 121 | stage.setAlwaysOnTop(true); 122 | stage.show(); 123 | stage.setAlwaysOnTop(false); 124 | }); 125 | }, "splash/launcher"); 126 | splashThread.start(); 127 | 128 | //Setting the max width and max height 129 | stage.setMinHeight(650.0d); 130 | stage.setMinWidth(973.0d); 131 | } 132 | 133 | public static void launchAdminTools(String[] args){ 134 | launch(args); 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /src/main/java/app/admintools/gui/HomeWindowController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package app.admintools.gui; 7 | 8 | import java.io.File; 9 | import java.io.IOException; 10 | import java.net.URL; 11 | import java.util.ArrayList; 12 | import java.util.ResourceBundle; 13 | 14 | import app.admintools.util.*; 15 | import javafx.fxml.FXML; 16 | import javafx.fxml.Initializable; 17 | import javafx.scene.control.ToggleButton; 18 | import javafx.scene.layout.AnchorPane; 19 | import javafx.scene.layout.FlowPane; 20 | import app.admintools.gui.credentials.credwizard.CredWizard; 21 | import app.admintools.security.credentials.Credentials; 22 | import app.admintools.security.credentials.CredentialsIO; 23 | 24 | import java.util.concurrent.atomic.AtomicBoolean; 25 | import javafx.collections.ListChangeListener; 26 | import javafx.scene.Node; 27 | import javafx.scene.control.Label; 28 | import com.lukeonuke.simplefxdialog.Dialog; 29 | import com.lukeonuke.simplefxdialog.img.DialogImage; 30 | 31 | /** 32 | * FXML Controller class 33 | * 34 | * @author lukak 35 | */ 36 | public class HomeWindowController implements Initializable { 37 | 38 | @FXML 39 | private AnchorPane rootPane; 40 | @FXML 41 | private FlowPane credCards; 42 | @FXML 43 | private ToggleButton rconButton; 44 | @FXML 45 | private ToggleButton statusButton; 46 | @FXML 47 | private ToggleButton settingsButton; 48 | @FXML 49 | private Label indicatorLabel; 50 | private final AtomicBoolean isWizardOpen = new AtomicBoolean(false); 51 | 52 | /** 53 | * Initializes the controller class. 54 | */ 55 | @Override 56 | public void initialize(URL url, ResourceBundle rb) { 57 | //Check beforehand 58 | if (credCards.getChildren().isEmpty()) { 59 | indicatorLabel.setText("Credentials empty, click the plus icon to add more!"); 60 | } else { 61 | indicatorLabel.setText(""); 62 | } 63 | //Add listener 64 | credCards.getChildren().addListener((ListChangeListener) es -> { 65 | if (credCards.getChildren().isEmpty()) { 66 | indicatorLabel.setText("Credentials empty, click the plus icon to add more!"); 67 | } else { 68 | indicatorLabel.setText(""); 69 | } 70 | }); 71 | 72 | refresh(); 73 | 74 | DRPC.updateStatus(DRPC.generatePresence("In home")); 75 | AtLogger.logger.info("Set home status"); 76 | } 77 | 78 | //Refreshes the credcards 79 | @SuppressWarnings("ResultOfMethodCallIgnored") 80 | private void refresh() { 81 | //Sets the credcards 82 | credCards.getChildren().clear(); 83 | try { 84 | if (new File(CredentialsIO.PATH).exists()) { 85 | if (CredentialsIO.readCredentials() != null) { 86 | for (Credentials credentials : CredentialsIO.readCredentials()) { 87 | credCards.getChildren().add(credentials.getCredCard()); 88 | } 89 | } 90 | } else { 91 | new File(CredentialsIO.PATH).createNewFile(); 92 | } 93 | } catch (IOException ioe) { 94 | AtLogger.logger.warning(AtLogger.formatException(ioe)); 95 | Dialog.okDialog(DialogImage.ERROR, "FATAL ERROR", ioe.getMessage()); 96 | Utill.exit(1); 97 | } 98 | } 99 | 100 | @FXML 101 | private void addNew() { 102 | if (!isWizardOpen.get()) { 103 | isWizardOpen.set(true); 104 | Credentials cred = CredWizard.showCredWizard(); 105 | if (cred != null) { 106 | try { 107 | ArrayList credList = CredentialsIO.readCredentials(); 108 | if (credList == null) { 109 | credList = new ArrayList<>(); 110 | } 111 | credList.add(cred); 112 | CredentialsIO.writeCredentials(credList); 113 | refresh(); 114 | } catch (IOException ex) { 115 | AtLogger.logger.warning(AtLogger.formatException(ex)); 116 | } 117 | } 118 | 119 | isWizardOpen.set(false); 120 | } 121 | } 122 | 123 | @FXML 124 | private void loadRcon() { 125 | if (Data.getInstance().getSelectedCredentials() != null) { 126 | WindowLoader.loadRcon(rootPane); 127 | } else { 128 | rconButton.setSelected(false); 129 | } 130 | } 131 | 132 | @FXML 133 | private void loadSettings() { 134 | if (Data.getInstance().getSelectedCredentials() != null) { 135 | WindowLoader.loadSettings(rootPane); 136 | } else { 137 | settingsButton.setSelected(false); 138 | } 139 | } 140 | 141 | @FXML 142 | private void loadStatus() { 143 | if (Data.getInstance().getSelectedCredentials() != null) { 144 | WindowLoader.loadStatus(rootPane); 145 | } else { 146 | statusButton.setSelected(false); 147 | } 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /src/main/java/app/admintools/gui/RconWindowController.java: -------------------------------------------------------------------------------- 1 | package app.admintools.gui; 2 | 3 | import app.admintools.gui.theme.ThemeReader; 4 | import app.admintools.textprocessing.Markup; 5 | import app.admintools.textprocessing.TellrawFormatter; 6 | import app.admintools.util.*; 7 | import com.lukeonuke.simplefxdialog.Dialog; 8 | import com.lukeonuke.simplefxdialog.img.DialogImage; 9 | import javafx.application.Platform; 10 | import javafx.beans.value.ChangeListener; 11 | import javafx.beans.value.ObservableValue; 12 | import javafx.concurrent.Worker; 13 | import javafx.event.EventHandler; 14 | import javafx.fxml.FXML; 15 | import javafx.fxml.Initializable; 16 | import javafx.scene.control.Label; 17 | import javafx.scene.control.ScrollPane; 18 | import javafx.scene.control.TextField; 19 | import javafx.scene.input.KeyCode; 20 | import javafx.scene.input.KeyEvent; 21 | import javafx.scene.layout.AnchorPane; 22 | import javafx.scene.web.WebEngine; 23 | import javafx.scene.web.WebErrorEvent; 24 | import javafx.scene.web.WebView; 25 | import net.kronos.rkon.core.ex.AuthenticationException; 26 | 27 | import java.io.File; 28 | import java.io.FileNotFoundException; 29 | import java.io.IOException; 30 | import java.net.URL; 31 | import java.util.ArrayList; 32 | import java.util.Arrays; 33 | import java.util.ResourceBundle; 34 | import java.util.Scanner; 35 | 36 | /** 37 | * 38 | * @author lukak 39 | */ 40 | public class RconWindowController implements Initializable { 41 | 42 | //Command history 43 | private ArrayList commandHistory = new ArrayList(); 44 | private int commandHistoryDeviation = 0; 45 | 46 | //FXML 47 | @FXML 48 | private TextField rconSend; 49 | @FXML 50 | private WebView rcon; 51 | @FXML 52 | private AnchorPane rootPane; 53 | @FXML 54 | private Label sendButton; 55 | @FXML 56 | private ScrollPane rconScroll; 57 | 58 | //Barebones mode variables 59 | @FXML 60 | private AnchorPane sidePane; 61 | @FXML 62 | private AnchorPane rconPane; 63 | 64 | //Web engine 65 | private WebEngine rconWebEngine; 66 | 67 | @Override 68 | public void initialize(URL url, ResourceBundle rb) { 69 | //Instantiate web engine 70 | rcon.contextMenuEnabledProperty().set(false); 71 | rcon.getEngine().setUserDataDirectory(new File("/webdata")); 72 | rconWebEngine = rcon.getEngine(); 73 | 74 | //Debug 75 | rconWebEngine.setOnError(new EventHandler() { 76 | @Override 77 | public void handle(WebErrorEvent event) { 78 | AtLogger.logger.severe(event.getMessage()); 79 | } 80 | }); 81 | 82 | //Setup autoscrolldown 83 | rcon.getEngine().getLoadWorker().stateProperty().addListener(new ChangeListener() { 84 | @Override 85 | public void changed(ObservableValue observable, Worker.State oldValue, Worker.State newValue) { 86 | if (newValue == Worker.State.SUCCEEDED) { 87 | rcon.getEngine().executeScript("window.scrollTo(0, document.body.scrollHeight);"); //JS JS JS JS JS JS JS JS JS 88 | } 89 | } 90 | }); 91 | 92 | //Read and set the rcon text from the data property if Data.rconTextData isnt null or write welcon message and set data 93 | if (Data.rconTextData != null) { 94 | refresh(); 95 | } else { 96 | //Initilise rcon text data 97 | Data.rconTextData = new ArrayList(); 98 | //Write welcome message if rcon children data is clear 99 | //Write welcome message 100 | write("§aAdmin§bTools§r, an administration tool by §9§lLukeOnuke§r"); 101 | } 102 | 103 | //Auto scroll 104 | rcon.heightProperty().addListener((observable, oldValue, newValue) -> rconScroll.setVvalue(1.0d)); 105 | 106 | //setup history entery 107 | rconSend.setOnKeyPressed((KeyEvent event) -> { 108 | boolean hasAction = false; 109 | int indexAfterAction = commandHistory.size() + commandHistoryDeviation + 1; 110 | if (event.getCode() == KeyCode.DOWN && -1 < indexAfterAction && indexAfterAction < commandHistory.size()) { 111 | commandHistoryDeviation++; 112 | hasAction = true; 113 | } 114 | indexAfterAction = commandHistory.size() + (commandHistoryDeviation - 1); 115 | if (event.getCode() == KeyCode.UP && -1 < indexAfterAction && indexAfterAction < commandHistory.size()) { 116 | commandHistoryDeviation--; 117 | hasAction = true; 118 | } 119 | if (hasAction) { 120 | int index = commandHistory.size() + commandHistoryDeviation; 121 | rconSend.setText(commandHistory.get(index)); 122 | } 123 | }); 124 | 125 | if (Data.startingUp) { 126 | //Connect to rcon 127 | 128 | Thread connect = new Thread(() -> { 129 | //setup variables 130 | boolean connected = true; 131 | //Disable all the text elements and buttons 132 | rconSend.setDisable(true); 133 | sendButton.setDisable(true); 134 | sidePane.setDisable(true); 135 | 136 | Data d = Data.getInstance(); 137 | write("§bConnecting to " + d.getSelectedCredentials().getIP() + ":" + d.getSelectedCredentials().getPort()); 138 | AtLogger.logger.info("Connecting to server"); 139 | try { 140 | CustomRcon cr = CustomRcon.getInstance(); 141 | //write connected message if its enabled 142 | if (d.getMessageNotify()) { 143 | cr.command(TellrawFormatter.assembleLoginTellraw(d.getMessageUsername())); 144 | } 145 | } catch (IOException ex) { 146 | AtLogger.logger.warning(AtLogger.formatException(ex)); 147 | connected = false; 148 | Platform.runLater(() -> { 149 | Dialog.okDialog(DialogImage.ERROR, "Connnection Error", "Couldn't connect to server.\n Probably an incorect IP."); 150 | WindowLoader.loadHome(rootPane); 151 | }); 152 | } catch (AuthenticationException ex) { 153 | AtLogger.logger.warning(AtLogger.formatException(ex)); 154 | connected = false; 155 | Platform.runLater(() -> { 156 | Dialog.okDialog(DialogImage.ERROR, "Connnection Error", "Couldn't authenticate with server. \nIncorrect password."); 157 | WindowLoader.loadHome(rootPane); 158 | }); 159 | } catch (Exception ex) { 160 | AtLogger.logger.warning(AtLogger.formatException(ex)); 161 | connected = false; 162 | Platform.runLater(() -> { 163 | Dialog.okDialog(DialogImage.ERROR, "Error", "General exception\n" + ex.getMessage()); 164 | WindowLoader.loadHome(rootPane); 165 | }); 166 | } 167 | //Write succsesfull connection 168 | if (connected) { 169 | Platform.runLater(() -> write("§bConnected to " + d.getSelectedCredentials().getIP() + ":" + d.getSelectedCredentials().getPort())); 170 | rconSend.setDisable(false); 171 | sendButton.setDisable(false); 172 | sidePane.setDisable(false); 173 | } else { 174 | Platform.runLater(() -> write("§cCouldnt connect to " + d.getSelectedCredentials().getIP() + ":" + d.getSelectedCredentials().getPort())); 175 | } 176 | }, "Connector Thread"); 177 | connect.start(); 178 | 179 | Data.startingUp = false; 180 | } 181 | 182 | DRPC.statusManagingServer(); 183 | } 184 | 185 | public void write(String message) { 186 | Data.rconTextData.add(Markup.generateMarkupParagraph(message)); 187 | refresh(); //refresh 188 | } 189 | 190 | public void refresh() { 191 | StringBuilder sb = new StringBuilder(); 192 | String color = "#5"; //Default is purple to indicate something went wrong 193 | try { 194 | color = ThemeReader.getConsoleColor(Data.getInstance().getSelectedTheme()); 195 | } catch (IOException ex) { 196 | AtLogger.logger.warning(AtLogger.formatException(ex)); 197 | } 198 | 199 | Data.rconTextData.add(0, ""); //add the style shit 200 | for (String element : Data.rconTextData) { 201 | sb.append(element); 202 | } 203 | Platform.runLater(() -> rconWebEngine.loadContent(sb.toString())); 204 | } 205 | 206 | /** 207 | * 1-st layer interpreter command send 208 | * 209 | * @param command the command to be sent 210 | */ 211 | private void sendCommand(String command) { 212 | CustomRcon cRcon; 213 | try { 214 | cRcon = CustomRcon.getInstance(); 215 | if (!command.equals("")) { 216 | write(Utill.getDate() + command); 217 | AtLogger.logger.info("Command sent to execution manager: " + command); 218 | //Internal command interpreter 219 | boolean isRightToSend = true; //Boolean that is checked when sending commands to server 220 | 221 | ArrayList splitCommand = new ArrayList<>(Arrays.asList(command.trim().split("\\s+"))); 222 | 223 | if (command.equals("stop")) { 224 | if (Dialog.okCancelDialog(DialogImage.WARNING, "Are you sure?", "Do you realy want to stop the server?" 225 | + System.lineSeparator() 226 | + "By pressing on you will be issuing a stop command to the server")) { 227 | 228 | isRightToSend = false; 229 | write("§bStopping the server."); 230 | cRcon.command("stop"); 231 | sendButton.disableProperty().set(true); 232 | rconSend.disableProperty().set(true); 233 | } 234 | } else if (command.equals("!help")) { 235 | isRightToSend = false; 236 | write("§bAdmin Tools internal command interpreter help: " + System.lineSeparator() 237 | + "\t!help - Help command" + System.lineSeparator() 238 | + "\t!clear - Clear the console" + System.lineSeparator() 239 | + "\t!exit - Exit the program and close the rcon connection" + System.lineSeparator()); 240 | } else if (command.equals("!clear")) { 241 | isRightToSend = false; 242 | Data.rconTextData.clear(); 243 | write("§bCleared console"); 244 | } else if (command.equals("!exit")) { 245 | isRightToSend = false; 246 | 247 | write("§bClosing connection and exiting..."); 248 | CustomRcon.getInstance().disconnect(); 249 | 250 | Utill.exit(commandHistoryDeviation); 251 | } else if (splitCommand.get(0).equals("!if")) { 252 | isRightToSend = false; 253 | if (logicalOperations(splitCommand.get(1))) { 254 | splitCommand.remove(0); 255 | splitCommand.remove(0); 256 | /* 257 | *Send the command that is after the if instruction ex. &if yes==yes 258 | *Send it this way so that it allows for nested if-s 259 | */ 260 | sendCommand(Utill.removeArrrayFormatting(splitCommand.toString())); 261 | } 262 | //Print statement 263 | } else if (splitCommand.get(0).equals("!print")) { 264 | isRightToSend = false; 265 | splitCommand.remove(0); 266 | write(Utill.removeArrrayFormatting(splitCommand.toString())); //Send the text after the print instruction 267 | 268 | } 269 | 270 | for (int i = 0; i < listScripts().size(); i++) { 271 | if (command.startsWith("@" + Utill.stripExtension(listScripts().get(i)))) { 272 | isRightToSend = false; 273 | ArrayList args = new ArrayList<>(Arrays.asList(command.split("[ ]"))); 274 | args.remove(0); 275 | executeScript(getScript(listScripts().get(i)), args); 276 | } 277 | } 278 | 279 | if (isRightToSend) { 280 | //Send and recive response 281 | write(cRcon.command(command)); 282 | AtLogger.logger.info("Command sent to server : " + command); 283 | } 284 | } 285 | } catch (IOException | AuthenticationException ex) { 286 | AtLogger.logger.warning(AtLogger.formatException(ex)); 287 | } 288 | 289 | //Set command history 290 | commandHistory.add(command); 291 | //Reset command history deviation 292 | commandHistoryDeviation = 0; 293 | //Reset textfield 294 | rconSend.setText(""); 295 | } 296 | 297 | @FXML 298 | private void send() { 299 | sendCommand(rconSend.getText()); 300 | } 301 | 302 | @FXML 303 | private void loadSettings() { 304 | WindowLoader.loadSettings(rootPane); 305 | } 306 | 307 | @FXML 308 | private void loadStatus() { 309 | WindowLoader.loadStatus(rootPane); 310 | } 311 | 312 | @FXML 313 | private void loadHome() { 314 | WindowLoader.loadHome(rootPane); 315 | } 316 | 317 | public static ArrayList listScripts() { 318 | ArrayList themeDir = new ArrayList<>(); //Netbeans takes a shite than complaians 319 | File[] themes = new File(Utill.getPath("assets/scripts/")).listFiles(); //Get a array of all files in the script folder 320 | for (File theme : themes) { //Go through them all 321 | if (theme.isFile()) { 322 | themeDir.add(theme.getName()); //Add its name to the returning arraylist if its a directory 323 | } 324 | } 325 | return themeDir; 326 | } 327 | 328 | public static String getScript(String scriptName) { 329 | return Utill.getPath("assets/scripts/" + scriptName); 330 | } 331 | 332 | private void executeScript(String scriptPath, ArrayList args) throws FileNotFoundException { 333 | // pass the path to the file as a parameter 334 | File file = new File(scriptPath); 335 | Scanner sc = new Scanner(file); 336 | 337 | write("┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉"); 338 | 339 | while (sc.hasNextLine()) { 340 | String instruction = sc.nextLine(); 341 | if (instruction != null) { 342 | for (int i = 0; i < args.size(); i++) { 343 | instruction = instruction.replace("arg" + i, args.get(i)); 344 | } 345 | 346 | if (instruction.startsWith("#")) { 347 | //Comment 348 | } else if (instruction.startsWith("@")) { 349 | //Call to new script, ignored 350 | 351 | } else { 352 | //Minecraft command, or 1-st layer interpreter command 353 | sendCommand(instruction); 354 | } 355 | } 356 | } 357 | } 358 | 359 | public static boolean logicalOperations(String operation) { 360 | if (operation.contains("==")) { 361 | return operation.split("==")[0].equals(operation.split("==")[1]); //Return true if the bit before the == is equal to the bit after the == 362 | } else if (operation.contains("!=")) { 363 | return !operation.split("!=")[0].equals(operation.split("!=")[1]); //Return true if the bit before the != is not equal to the bit after the != 364 | } 365 | return false; 366 | } 367 | } 368 | -------------------------------------------------------------------------------- /src/main/java/app/admintools/gui/SettingsWindowController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package app.admintools.gui; 7 | 8 | import java.io.IOException; 9 | import java.net.URL; 10 | import java.util.ArrayList; 11 | import java.util.ResourceBundle; 12 | 13 | import app.admintools.util.*; 14 | import javafx.fxml.FXML; 15 | import javafx.fxml.Initializable; 16 | import javafx.scene.control.ChoiceBox; 17 | import javafx.scene.control.Label; 18 | import javafx.scene.control.RadioButton; 19 | import javafx.scene.control.Slider; 20 | import javafx.scene.control.TextField; 21 | import javafx.scene.input.KeyEvent; 22 | import javafx.scene.layout.AnchorPane; 23 | import app.admintools.gui.theme.ThemeReader; 24 | import com.lukeonuke.simplefxdialog.Dialog; 25 | import com.lukeonuke.simplefxdialog.img.DialogImage; 26 | 27 | /** 28 | * FXML Controller class 29 | * 30 | * @author lukak 31 | */ 32 | public class SettingsWindowController implements Initializable { 33 | 34 | @FXML 35 | private AnchorPane rootPane; 36 | @FXML 37 | private Slider settingsApiRequestR; 38 | @FXML 39 | private TextField settingsQuerryRR; 40 | @FXML 41 | private Label sARR; //settings api request rate 42 | //@FXML 43 | //private Label sQRR; //settings querry request rate 44 | 45 | @FXML 46 | private RadioButton settingsMsgNotify; 47 | @FXML 48 | private RadioButton settingsMsgOverrideSay; 49 | @FXML 50 | private TextField settingsMsgUsername; 51 | 52 | @FXML 53 | private ChoiceBox themeChoice; 54 | 55 | /** 56 | * Initializes the controller class. 57 | */ 58 | @Override 59 | public void initialize(URL url, ResourceBundle rb) { 60 | Data data = Data.refresh(); 61 | try{ 62 | settingsApiRequestR.setValue(data.getQuerryMojangApiRefreshRate()); 63 | settingsQuerryRR.setText(String.valueOf(data.getQuerryMcRefreshRate())); 64 | settingsMsgOverrideSay.setSelected(data.getMessageOverwriteSay()); 65 | settingsMsgNotify.setSelected(data.getMessageNotify()); 66 | settingsMsgUsername.setText(data.getMessageUsername()); 67 | 68 | //Set choicebox choices 69 | ThemeReader.listThemes().forEach((choice) -> { 70 | themeChoice.getItems().add(choice); 71 | }); 72 | 73 | themeChoice.setValue(data.getSelectedTheme()); 74 | } catch (IOException e) { 75 | AtLogger.logger.severe(AtLogger.formatException(e)); 76 | } 77 | 78 | refresh(); 79 | 80 | DRPC.statusManagingServer(); 81 | } 82 | 83 | @FXML 84 | private void loadRcon() { 85 | WindowLoader.loadRcon(rootPane); 86 | } 87 | 88 | @FXML 89 | private void loadStatus() { 90 | WindowLoader.loadStatus(rootPane); 91 | } 92 | 93 | @FXML 94 | private void loadHome() { 95 | WindowLoader.loadHome(rootPane); 96 | } 97 | 98 | @FXML 99 | private void onKeyPressed(KeyEvent ke) { 100 | if (ke.getText().equals("s") && ke.isControlDown()) { 101 | apply(); 102 | Dialog.okDialog(DialogImage.INFO, "Settings saved", "Your settings have been saved"); 103 | } 104 | } 105 | 106 | @FXML 107 | private void refresh() { 108 | sARR.setText(String.valueOf(Math.round(settingsApiRequestR.getValue())) + "s"); 109 | } 110 | 111 | @FXML 112 | private void apply() { 113 | 114 | try { 115 | Data.write(DataType.QUERRY_MC_REFRESHRATE, settingsQuerryRR.getText()); 116 | Data.write(DataType.QUERRY_API_REFRESHRATE, String.valueOf(Math.round(settingsApiRequestR.getValue()))); 117 | Data.write(DataType.MESSAGE_SEND_ON_LOGON, String.valueOf(settingsMsgNotify.selectedProperty().get())); 118 | Data.write(DataType.MESSAGE_OVERWRITE_SAY, String.valueOf(settingsMsgOverrideSay.selectedProperty().get())); 119 | Data.write(DataType.USERNAME, settingsMsgUsername.getText()); 120 | Data.write(DataType.THEME, themeChoice.getValue().toString()); 121 | } catch (IOException e) { 122 | AtLogger.logger.severe(AtLogger.formatException(e)); 123 | } 124 | 125 | 126 | //Actualy have to refresh the theme 127 | //And refresh the Data singleton 128 | Utill.setSelectedTheme(rootPane); 129 | } 130 | 131 | @FXML 132 | private void reset() { 133 | settingsQuerryRR.setText(Data.defaults.get(DataType.QUERRY_MC_REFRESHRATE)); 134 | settingsApiRequestR.setValue(Double.valueOf(Data.defaults.get(DataType.QUERRY_API_REFRESHRATE))); 135 | refresh(); 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/main/java/app/admintools/gui/StatusWindowController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package app.admintools.gui; 7 | 8 | import java.io.IOException; 9 | import java.net.URL; 10 | import java.util.ArrayList; 11 | import java.util.ResourceBundle; 12 | 13 | import app.admintools.AdminTools; 14 | import javafx.application.Platform; 15 | import javafx.fxml.FXML; 16 | import javafx.fxml.Initializable; 17 | import javafx.scene.control.Label; 18 | import javafx.scene.control.ListView; 19 | import javafx.scene.control.ProgressBar; 20 | import javafx.scene.image.Image; 21 | import javafx.scene.image.ImageView; 22 | import javafx.scene.input.MouseEvent; 23 | import javafx.scene.layout.AnchorPane; 24 | import javafx.scene.layout.Pane; 25 | import app.admintools.util.WindowLoader; 26 | import app.admintools.querry.api.ApiQuerry; 27 | import app.admintools.querry.mc.MinecraftPing; 28 | import app.admintools.querry.mc.MinecraftPingOptions; 29 | import app.admintools.querry.mc.MinecraftPingReply; 30 | import app.admintools.querry.mc.QuerryUtils; 31 | import app.admintools.threadmanager.ThreadManager; 32 | import app.admintools.threadmanager.ThreadType; 33 | import app.admintools.util.AtLogger; 34 | import app.admintools.util.Data; 35 | 36 | /** 37 | * FXML Controller class 38 | * 39 | * @author lukak 40 | */ 41 | public class StatusWindowController implements Initializable { 42 | 43 | @FXML 44 | private AnchorPane rootPane; 45 | /* 46 | Status dots 47 | Naming scheme is: 48 | sd 49 | s-status 50 | d-dot 51 | statusDot but shortened 52 | */ 53 | 54 | //For mc serv status 55 | @FXML 56 | private ImageView sFavicon; 57 | @FXML 58 | private Label sVer; 59 | @FXML 60 | private Label sPlayers; 61 | @FXML 62 | private ListView sOnlinePlayers; 63 | 64 | /** 65 | * Initializes the controller class. 66 | * 67 | * @param url 68 | * @param rb 69 | */ 70 | @Override 71 | public void initialize(URL url, ResourceBundle rb) { 72 | tickMcRefresh(); 73 | } 74 | 75 | @FXML 76 | private void loadRcon() { 77 | WindowLoader.loadRcon(rootPane); 78 | } 79 | 80 | @FXML 81 | private void loadSettings() { 82 | WindowLoader.loadSettings(rootPane); 83 | } 84 | 85 | @FXML 86 | private void loadHome() { 87 | WindowLoader.loadHome(rootPane); 88 | } 89 | 90 | @FXML 91 | private void mcStatusRefresh() { 92 | Thread mcsr = new Thread(() -> { 93 | Data d = Data.getInstance(); //get data class instance 94 | MinecraftPingReply data; //get querry 95 | try { 96 | data = new MinecraftPing().getPing(new MinecraftPingOptions().setHostname(d.getSelectedCredentials().getIP()).setPort(d.getSelectedCredentials().getPingPort())); //create querry 97 | 98 | //Set all the text and images 99 | Platform.runLater(() -> { 100 | sVer.setText("Version: " + data.getVersion().getName()); 101 | sPlayers.setText("Players: " + data.getPlayers().getOnline() + " / " + data.getPlayers().getMax()); 102 | if (data.getFavicon() != null) { 103 | sFavicon.setImage(QuerryUtils.convertToImage(data.getFavicon())); 104 | } else { 105 | sFavicon.setImage(new Image(AdminTools.class.getResourceAsStream("/img/unknown-server.png"))); 106 | } 107 | }); 108 | 109 | //Set player list 110 | Platform.runLater(() -> { 111 | if (data.getPlayers().getSample() != null) { 112 | try { 113 | if (sOnlinePlayers.getItems() != null) { 114 | sOnlinePlayers.getItems().clear(); 115 | } 116 | for (int i = 0; i < data.getPlayers().getSample().size(); i++) { 117 | sOnlinePlayers.getItems().add(data.getPlayers().getSample().get(i).getName()); 118 | } 119 | 120 | } catch (Exception e) { 121 | AtLogger.logger.warning(AtLogger.formatException(e)); 122 | } 123 | } 124 | }); 125 | 126 | } catch (IOException ex) { 127 | AtLogger.logger.warning(AtLogger.formatException(ex)); 128 | } 129 | 130 | }); 131 | mcsr.start(); 132 | } 133 | 134 | private void tickMcRefresh() { 135 | Thread tmrt = new Thread(() -> { 136 | Platform.runLater(() -> { 137 | mcStatusRefresh(); 138 | }); 139 | Data d = Data.getInstance(); 140 | try { 141 | int timeSleep = d.getQuerryMcRefreshRate() * 1000; 142 | for (int i = 0; i < timeSleep / 500; i++) { 143 | if (!Data.isOnStatusWindow) { 144 | return; 145 | } 146 | Thread.sleep(500); 147 | } 148 | } catch (InterruptedException | IOException ex) { 149 | AtLogger.logger.warning(AtLogger.formatException(ex)); 150 | } 151 | tickMcRefresh(); 152 | 153 | }); 154 | tmrt.setName("McTick"); 155 | ThreadManager.startThread(tmrt, ThreadType.ASYNCJOB); 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /src/main/java/app/admintools/gui/credentials/credcard/CredCard.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package app.admintools.gui.credentials.credcard; 7 | 8 | import java.io.IOException; 9 | import java.util.ArrayList; 10 | import javafx.animation.KeyFrame; 11 | import javafx.animation.KeyValue; 12 | import javafx.animation.Timeline; 13 | import javafx.scene.Node; 14 | import javafx.scene.control.Label; 15 | import javafx.scene.effect.DropShadow; 16 | import javafx.scene.layout.AnchorPane; 17 | import javafx.scene.layout.FlowPane; 18 | import javafx.scene.paint.Color; 19 | import javafx.scene.shape.SVGPath; 20 | import javafx.scene.text.Text; 21 | import javafx.util.Duration; 22 | import app.admintools.gui.credentials.credwizard.CredWizard; 23 | import app.admintools.security.credentials.Credentials; 24 | import app.admintools.security.credentials.CredentialsIO; 25 | import app.admintools.util.AtLogger; 26 | import app.admintools.util.CustomRcon; 27 | import app.admintools.util.Data; 28 | import app.admintools.util.WindowLoader; 29 | import java.util.concurrent.atomic.AtomicBoolean; 30 | 31 | /** 32 | * 33 | * @author lukak 34 | */ 35 | public class CredCard { 36 | 37 | /** 38 | * Creates the credcards that are used in the loginscreen 39 | * 40 | * @param titleContents 41 | * @param ip 42 | * @param credentials 43 | * @return 44 | */ 45 | public static AnchorPane createCredCard(String titleContents, String ip, Credentials credentials) { 46 | AnchorPane ap = new AnchorPane(); 47 | Label title; 48 | Text minus; 49 | Label ipField; 50 | SVGPath editIcon; 51 | AnchorPane edit; 52 | AtomicBoolean isOpenWindow = new AtomicBoolean(); 53 | 54 | title = new Label(); 55 | minus = new Text(); 56 | ipField = new Label(); 57 | editIcon = new SVGPath(); 58 | edit = new AnchorPane(); 59 | 60 | ap.setPrefHeight(115.0); 61 | ap.setPrefWidth(370.0); 62 | ap.getStyleClass().add("loginCard"); 63 | ap.setId("credCard"); 64 | 65 | DropShadow dropShadow = new DropShadow(0, Color.web("#1f1f1f")); 66 | dropShadow.setOffsetX(0d); 67 | dropShadow.setOffsetY(0d); 68 | ap.setEffect(dropShadow); 69 | 70 | //Create the hovershadow effects 71 | Timeline dropShadowDrop = new Timeline(new KeyFrame(Duration.seconds(.35d), new KeyValue(dropShadow.radiusProperty(), 20.0))); 72 | Timeline dropShadowRemove = new Timeline(new KeyFrame(Duration.seconds(.35d), new KeyValue(dropShadow.radiusProperty(), 0.0))); 73 | 74 | //Display the events on mouse hover events 75 | ap.setOnMouseEntered(me -> { 76 | if (dropShadowRemove.getStatus() == Timeline.Status.RUNNING) { 77 | dropShadowRemove.stop(); 78 | } 79 | dropShadowDrop.play(); 80 | }); 81 | ap.setOnMouseExited(me -> { 82 | if (dropShadowDrop.getStatus() == Timeline.Status.RUNNING) { 83 | dropShadowDrop.stop(); 84 | } 85 | dropShadowRemove.play(); 86 | }); 87 | 88 | ap.setOnMouseClicked(me -> { 89 | String id = "credCard"; 90 | if (((Node) me.getTarget()).getId() != null) { 91 | id = ((Node) me.getTarget()).getId(); 92 | } 93 | if (id.equals("minus")) { 94 | try { 95 | ArrayList creds = CredentialsIO.readCredentials(); 96 | creds.remove(credentials); 97 | CredentialsIO.writeCredentials(creds); 98 | ((FlowPane) ap.getParent()).getChildren().remove(ap); 99 | } catch (IOException ex) { 100 | AtLogger.logger.warning(AtLogger.formatException(ex)); 101 | } 102 | } else if (id.equals("edit")) { 103 | if (!isOpenWindow.get()) { 104 | isOpenWindow.set(true); 105 | //Show credentials wizard 106 | Credentials editedCreds = CredWizard.showCredWizard(credentials); 107 | if (editedCreds != null) { 108 | try { 109 | FlowPane parrent = (FlowPane) ap.getParent(); 110 | ArrayList creds = CredentialsIO.readCredentials(); 111 | creds.remove(credentials); //Remove the old one (this one) 112 | creds.add(editedCreds); //Add the edited one (new one) 113 | CredentialsIO.writeCredentials(creds); 114 | parrent.getChildren().remove(ap); //Remove this card 115 | //Display new card 116 | parrent.getChildren().add(editedCreds.getCredCard()); 117 | } catch (IOException ex) { 118 | AtLogger.logger.warning(AtLogger.formatException(ex)); 119 | } 120 | } 121 | isOpenWindow.set(false); 122 | } 123 | 124 | } else { 125 | //Nullify the current custom rcon instance 126 | CustomRcon.setToNull(); 127 | //set tje credentials 128 | Data.getInstance().setSelectedCredentials(credentials); 129 | WindowLoader.loadRcon(((AnchorPane) ap.getScene().getRoot())); 130 | } 131 | }); 132 | 133 | AnchorPane.setLeftAnchor(title, 4.0); 134 | AnchorPane.setTopAnchor(title, 4.0); 135 | title.setLayoutX(3.0); 136 | title.setLayoutY(4.0); 137 | title.setPrefHeight(30.0); 138 | title.setPrefWidth(319.0); 139 | 140 | title.getStyleClass().add("ctitle"); 141 | title.setText(titleContents); 142 | 143 | AnchorPane.setRightAnchor(minus, 17.0); 144 | AnchorPane.setTopAnchor(minus, 24.0); 145 | minus.setBoundsType(javafx.scene.text.TextBoundsType.VISUAL); 146 | 147 | minus.setLayoutX(334.0); 148 | minus.setLayoutY(39.5029296875); 149 | minus.setLineSpacing(2.0); 150 | minus.setStrokeType(javafx.scene.shape.StrokeType.OUTSIDE); 151 | 152 | minus.setStrokeWidth(0.0); 153 | minus.getStyleClass().add("plus"); 154 | minus.setText("-"); 155 | minus.setWrappingWidth(13.330078125); 156 | minus.setId("minus"); 157 | 158 | ipField.setLayoutX(13.0); 159 | ipField.setLayoutY(57.0); 160 | ipField.setPrefHeight(30.0); 161 | ipField.setPrefWidth(334.0); 162 | ipField.getStyleClass().add("text"); 163 | ipField.setText(ip); 164 | ipField.setTextAlignment(javafx.scene.text.TextAlignment.CENTER); 165 | 166 | editIcon.setContent("M 13.96875 12.125 L 15.078125 11 C 15.253906 10.824219 15.554688 10.949219 15.554688 11.199219 L 15.554688 16.3125 C 15.554688 17.242188 14.808594 18 13.890625 18 L 1.667969 18 C 0.746094 18 0 17.242188 0 16.3125 L 0 3.9375 C 0 3.007812 0.746094 2.25 1.667969 2.25 L 11.164062 2.25 C 11.410156 2.25 11.535156 2.550781 11.359375 2.730469 L 10.25 3.855469 C 10.199219 3.910156 10.128906 3.9375 10.050781 3.9375 L 1.667969 3.9375 L 1.667969 16.3125 L 13.890625 16.3125 L 13.890625 12.320312 C 13.890625 12.25 13.917969 12.179688 13.96875 12.125 Z M 19.40625 5.03125 L 10.289062 14.261719 L 7.148438 14.613281 C 6.238281 14.714844 5.464844 13.9375 5.566406 13.011719 L 5.914062 9.832031 L 15.03125 0.601562 C 15.828125 -0.203125 17.109375 -0.203125 17.902344 0.601562 L 19.402344 2.121094 C 20.199219 2.925781 20.199219 4.230469 19.40625 5.03125 Z M 15.976562 6.117188 L 13.957031 4.074219 L 7.507812 10.609375 L 7.253906 12.90625 L 9.519531 12.648438 Z M 18.226562 3.316406 L 16.726562 1.796875 C 16.582031 1.652344 16.351562 1.652344 16.210938 1.796875 L 15.140625 2.882812 L 17.15625 4.925781 L 18.230469 3.839844 C 18.367188 3.691406 18.367188 3.460938 18.226562 3.316406 Z M 18.226562 3.316406"); 167 | editIcon.getStyleClass().add("plus"); 168 | editIcon.setId("edit"); 169 | 170 | edit.getChildren().add(editIcon); 171 | edit.getStyleClass().add("edit"); 172 | AnchorPane.setRightAnchor(edit, 37.0); 173 | AnchorPane.setTopAnchor(edit, 15.0); 174 | edit.setId("edit"); 175 | 176 | ap.getChildren().add(title); 177 | ap.getChildren().add(minus); 178 | ap.getChildren().add(ipField); 179 | ap.getChildren().add(edit); 180 | 181 | return ap; 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /src/main/java/app/admintools/gui/credentials/credwizard/CredWizard.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package app.admintools.gui.credentials.credwizard; 7 | 8 | import java.net.InetAddress; 9 | import java.net.UnknownHostException; 10 | import java.util.concurrent.atomic.AtomicBoolean; 11 | 12 | import app.admintools.util.Utill; 13 | import javafx.scene.Scene; 14 | import javafx.scene.control.Label; 15 | import javafx.scene.control.PasswordField; 16 | import javafx.scene.control.TextField; 17 | import javafx.scene.effect.DropShadow; 18 | import javafx.scene.layout.AnchorPane; 19 | import javafx.scene.text.Text; 20 | import javafx.stage.Stage; 21 | import app.admintools.security.credentials.Credentials; 22 | import app.admintools.util.Data; 23 | import javafx.stage.StageStyle; 24 | 25 | /** 26 | * 27 | * @author lukak 28 | */ 29 | public class CredWizard { 30 | 31 | private static final double OFFSET = 50d; 32 | 33 | /** 34 | * Creates and shows a credentials wizard 35 | * @param credentials The credentials to edit 36 | * @return Credentials 37 | */ 38 | public static Credentials showCredWizard(Credentials credentials) { 39 | //SPOOKY SCARY JFX CODE 40 | AnchorPane ap; 41 | AnchorPane anchorPane; 42 | Text text; 43 | DropShadow dropShadow; 44 | TextField name; 45 | TextField ipAdress; 46 | TextField port; 47 | PasswordField password; 48 | TextField pingPort; 49 | Label button; 50 | Label status; 51 | 52 | ap = new AnchorPane(); 53 | anchorPane = new AnchorPane(); 54 | text = new Text(); 55 | dropShadow = new DropShadow(); 56 | name = new TextField(); 57 | ipAdress = new TextField(); 58 | port = new TextField(); 59 | password = new PasswordField(); 60 | pingPort = new TextField(); 61 | button = new Label(); 62 | status = new Label(); 63 | 64 | ap.setId("AnchorPane"); 65 | ap.setPrefHeight(377.0); 66 | ap.setPrefWidth(354.0); 67 | ap.getStyleClass().add("sidePane"); 68 | 69 | AnchorPane.setLeftAnchor(anchorPane, 0.0); 70 | AnchorPane.setRightAnchor(anchorPane, 0.0); 71 | AnchorPane.setTopAnchor(anchorPane, 0.0); 72 | anchorPane.setPrefHeight(71.0); 73 | anchorPane.setPrefWidth(600.0); 74 | anchorPane.getStyleClass().add("titlePane"); 75 | 76 | AnchorPane.setLeftAnchor(text, 12.0); 77 | AnchorPane.setTopAnchor(text, 7.8359375); 78 | text.setLayoutX(12.0); 79 | text.setLayoutY(51.0); 80 | text.setStrokeType(javafx.scene.shape.StrokeType.OUTSIDE); 81 | text.setStrokeWidth(0.0); 82 | text.getStyleClass().add("title"); 83 | text.setText("Credentials Wizard"); 84 | 85 | dropShadow.setColor(javafx.scene.paint.Color.web("#000000a3")); 86 | dropShadow.setHeight(11.86); 87 | dropShadow.setRadius(7.715); 88 | dropShadow.setSpread(0.4); 89 | anchorPane.setEffect(dropShadow); 90 | 91 | AnchorPane.setLeftAnchor(name, 9.0); 92 | AnchorPane.setRightAnchor(name, 9.0); 93 | AnchorPane.setTopAnchor(name, 96.0); 94 | name.setLayoutX(9.0); 95 | name.setLayoutY(96.0); 96 | name.setPrefHeight(27.0); 97 | name.setPrefWidth(331.0); 98 | name.setPromptText("Name"); 99 | name.getStyleClass().add("rconTextField"); 100 | 101 | AnchorPane.setLeftAnchor(ipAdress, 9.0); 102 | AnchorPane.setRightAnchor(ipAdress, 9.0); 103 | AnchorPane.setTopAnchor(ipAdress, 96.0 + OFFSET); 104 | ipAdress.setLayoutX(9.0); 105 | ipAdress.setLayoutY(96.0 + OFFSET); 106 | ipAdress.setPrefHeight(27.0); 107 | ipAdress.setPrefWidth(331.0); 108 | ipAdress.setPromptText("IP adress"); 109 | ipAdress.getStyleClass().add("rconTextField"); 110 | 111 | AnchorPane.setLeftAnchor(port, 9.0); 112 | AnchorPane.setRightAnchor(port, 9.0); 113 | AnchorPane.setTopAnchor(port, 96.0 + 2 * OFFSET); 114 | port.setLayoutX(9.0); 115 | port.setLayoutY(96.0 + 2 * OFFSET); 116 | port.setPrefHeight(27.0); 117 | port.setPrefWidth(331.0); 118 | port.setPromptText("Port"); 119 | port.getStyleClass().add("rconTextField"); 120 | 121 | AnchorPane.setLeftAnchor(password, 9.0); 122 | AnchorPane.setRightAnchor(password, 9.0); 123 | AnchorPane.setTopAnchor(password, 96.0 + 3 * OFFSET); 124 | password.setLayoutX(9.0); 125 | password.setLayoutY(96.0 + 3 * OFFSET); 126 | password.setPrefHeight(25.0); 127 | password.setPrefWidth(331.0); 128 | password.setPromptText("Password"); 129 | password.getStyleClass().add("rconTextField"); 130 | 131 | AnchorPane.setLeftAnchor(pingPort, 9.0); 132 | AnchorPane.setRightAnchor(pingPort, 9.0); 133 | AnchorPane.setTopAnchor(pingPort, 96.0 + 4 * OFFSET); 134 | pingPort.setLayoutX(9.0); 135 | pingPort.setLayoutY(96.0 + 4 * OFFSET); 136 | pingPort.setPrefHeight(27.0); 137 | pingPort.setPrefWidth(331.0); 138 | pingPort.setPromptText("Ping port - optional (if left unfilled it defaults to 25565)"); 139 | pingPort.getStyleClass().add("rconTextField"); 140 | 141 | AnchorPane.setBottomAnchor(button, 9.0); 142 | AnchorPane.setRightAnchor(button, 9.0); 143 | button.setLayoutX(312.0); 144 | button.setLayoutY(313.0); 145 | button.getStyleClass().add("labelButton"); 146 | button.setText("Connect"); 147 | 148 | AnchorPane.setBottomAnchor(status, 12.0); 149 | AnchorPane.setLeftAnchor(status, 9.0); 150 | status.setLayoutX(9.0); 151 | status.setLayoutY(286.0); 152 | status.setPrefHeight(20.0); 153 | status.setPrefWidth(272.0); 154 | status.getStyleClass().add("text"); 155 | status.setText(""); 156 | 157 | anchorPane.getChildren().add(text); 158 | ap.getChildren().add(name); 159 | ap.getChildren().add(anchorPane); 160 | ap.getChildren().add(ipAdress); 161 | ap.getChildren().add(port); 162 | ap.getChildren().add(password); 163 | ap.getChildren().add(pingPort); 164 | ap.getChildren().add(button); 165 | ap.getChildren().add(status); 166 | 167 | //Read the credentials and set the stuff acordingly 168 | 169 | //Check if credentials aren't null 170 | if(credentials != null){ 171 | //Set all the stuffs 172 | name.setText(credentials.getName()); 173 | ipAdress.setText(credentials.getIP()); 174 | port.setText(String.valueOf(credentials.getPort())); 175 | password.setText(credentials.getPassword()); 176 | pingPort.setText(String.valueOf(credentials.getPingPort())); 177 | } 178 | 179 | //Create window 180 | Scene scene = new Scene(ap); 181 | Utill.setSelectedTheme(scene); 182 | Stage stage = new Stage(); 183 | stage.setScene(scene); 184 | stage.setAlwaysOnTop(true); 185 | stage.setResizable(false); 186 | stage.initStyle(StageStyle.UTILITY); 187 | 188 | //Credentials to return 189 | AtomicBoolean isValid = new AtomicBoolean(false); 190 | 191 | button.setOnMouseClicked((me) -> { 192 | boolean valid = true; 193 | try { 194 | //Check all the imputs 195 | Integer.valueOf(port.getText()); 196 | //Dont check pingport if empty 197 | if (!pingPort.getText().equals("")) { 198 | Integer.valueOf(pingPort.getText()); 199 | } 200 | InetAddress.getByName(ipAdress.getText()); 201 | //Catch all exeptions and set valid to false and set indicator 202 | } catch (NumberFormatException ex) { 203 | valid = false; 204 | status.setText("Please input a valid intiger into the port or ping port field"); 205 | } catch (UnknownHostException ex) { 206 | valid = false; 207 | status.setText("Please input a valid IP address"); 208 | } 209 | 210 | //Is everything valid? 211 | if (valid) { 212 | status.setText("Setting up"); 213 | isValid.set(valid); 214 | stage.close(); 215 | } 216 | }); 217 | 218 | stage.showAndWait(); 219 | 220 | if (isValid.get()) { 221 | //If the user left the pingport field empty fill it in with the default port 222 | if (pingPort.getText().equals("")) { 223 | pingPort.setText("25565"); 224 | } 225 | return new Credentials(ipAdress.getText(), Integer.valueOf(port.getText()), password.getText(), name.getText(), Integer.valueOf(pingPort.getText())); 226 | } 227 | return null; 228 | } 229 | 230 | /** 231 | * Show credentials wizard without having a credentials to edit. 232 | * @return Credentials created out of the good stuff. 233 | */ 234 | public static Credentials showCredWizard(){ 235 | return showCredWizard(null); 236 | //Give ya meet a good old rub. Wow somebody reading the source code, thanks for that -LukeOnuke 24.10.2020 00:40 . 237 | } 238 | } 239 | -------------------------------------------------------------------------------- /src/main/java/app/admintools/gui/splash/SplashScreen.java: -------------------------------------------------------------------------------- 1 | package app.admintools.gui.splash; 2 | 3 | import app.admintools.util.Data; 4 | import app.admintools.util.Utill; 5 | import app.admintools.util.Version; 6 | import javafx.scene.Node; 7 | import javafx.scene.control.Label; 8 | import javafx.scene.control.ProgressBar; 9 | import javafx.scene.image.Image; 10 | import javafx.scene.image.ImageView; 11 | import javafx.scene.layout.*; 12 | 13 | public class SplashScreen extends AnchorPane { 14 | ProgressBar progressBar = new ProgressBar(); 15 | AnchorPane windowArea = new AnchorPane(); 16 | 17 | public SplashScreen() { 18 | this.getChildren().add(progressBar); 19 | this.getChildren().add(windowArea); 20 | setup(); 21 | } 22 | 23 | private SplashScreen(Node... children) { 24 | } 25 | 26 | private void setup() { 27 | Utill.setSelectedTheme(this); 28 | this.setPrefHeight(300d); 29 | this.setPrefWidth(510d); 30 | AnchorPane.setBottomAnchor(progressBar, 0d); 31 | AnchorPane.setLeftAnchor(progressBar, 0d); 32 | AnchorPane.setRightAnchor(progressBar, 0d); 33 | 34 | AnchorPane.setRightAnchor(windowArea, 0d); 35 | AnchorPane.setLeftAnchor(windowArea, 0d); 36 | AnchorPane.setTopAnchor(windowArea, 0d); 37 | AnchorPane.setBottomAnchor(windowArea, 20d); 38 | 39 | windowArea.setStyle("-fx-background-color: white;"); 40 | 41 | // new Image(url) 42 | ImageView img; 43 | Image image = new Image("file:assets/img/splash_screen.png", this.getPrefWidth(), this.getPrefHeight() - 20, false, true); 44 | 45 | img = new ImageView(image); 46 | img.setSmooth(true); 47 | 48 | Label versionLabel = new Label(); 49 | Version version = Version.getInstance(); 50 | 51 | if(version.isDevelopmentVersion()){ 52 | versionLabel.setText("Development version : " + version.getSnapshotVersion() + "[" + version.getFullVersionNumber()+ "]"); 53 | } 54 | versionLabel.setTranslateZ(-10); 55 | versionLabel.setStyle("-fx-font-size: 20px;"); 56 | versionLabel.getStyleClass().add("text"); 57 | 58 | windowArea.getChildren().addAll(versionLabel, img); 59 | 60 | AnchorPane.setBottomAnchor(versionLabel, 0d); 61 | AnchorPane.setLeftAnchor(versionLabel, 0d); 62 | 63 | this.getStyleClass().add("splash"); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/app/admintools/gui/theme/ThemeReader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package app.admintools.gui.theme; 7 | 8 | import app.admintools.util.Utill; 9 | import javafx.scene.Node; 10 | import javafx.scene.layout.AnchorPane; 11 | 12 | import java.io.File; 13 | import java.io.FileNotFoundException; 14 | import java.util.ArrayList; 15 | import java.util.Scanner; 16 | 17 | /** 18 | * 19 | * @author lukak 20 | */ 21 | public class ThemeReader { 22 | 23 | public static ArrayList listThemes() { 24 | ArrayList themeDir = new ArrayList(); //Netbeans takes a shite than complaians 25 | File[] themes = new File(Utill.getPath("assets/themes/")).listFiles(); //Get a array of all files in the themes folder 26 | for (File theme : themes) { //Go through them all 27 | if (theme.isDirectory()) { 28 | themeDir.add(theme.getName()); //Add its name to the returning arraylist if its a directory 29 | } 30 | } 31 | return themeDir; 32 | } 33 | 34 | public static String getCss(String themeName) { 35 | return Utill.getPath("file:assets/themes/" + themeName + "/style.css"); 36 | } 37 | 38 | public static String getConsoleColor(String themeName) throws FileNotFoundException { 39 | File metaFile = new File(Utill.getPath("assets/themes/" + themeName + "/consolecolor.txt")); 40 | Scanner reader = new Scanner(metaFile); 41 | String color = reader.nextLine(); 42 | reader.close(); 43 | return color; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/app/admintools/img/unknown_server.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LukeOnuke/AdminTools/0c7fb6b85a304d9966b64568d306b3c8b1afb184/src/main/java/app/admintools/img/unknown_server.png -------------------------------------------------------------------------------- /src/main/java/app/admintools/querry/api/ApiQuerry.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package app.admintools.querry.api; 7 | 8 | import java.io.IOException; 9 | import java.util.ArrayList; 10 | import app.admintools.util.Utill; 11 | 12 | /** 13 | * 14 | * @author lukak 15 | */ 16 | public class ApiQuerry { 17 | 18 | /** 19 | * Gets a querry 20 | * 21 | * minecraft.net session.minecraft.net account.mojang.com 22 | * authserver.mojang.com sessionserver.mojang.com api.mojang.com 23 | * textures.minecraft.net mojang.com 24 | * 25 | * @throws IOException 26 | */ 27 | public static ArrayList querry() throws IOException { 28 | ArrayList data = new ArrayList(); 29 | String querryRaw = Utill.getHTTPRequest("https://status.mojang.com/check"); 30 | //replace all the pescy JSON (delet dis JSON) 31 | querryRaw = querryRaw.replace("}", ""); 32 | querryRaw = querryRaw.replace("{", ""); 33 | querryRaw = querryRaw.replace("\"", ""); 34 | querryRaw = querryRaw.replace("]", ""); 35 | querryRaw = querryRaw.replace("[", ""); 36 | //replace green with more appetising colour 37 | querryRaw = querryRaw.replace("green", "yellowgreen"); 38 | String[] splitQuerry = querryRaw.split(","); 39 | for (String s : splitQuerry) { 40 | data.add(s.split(":")[1]); 41 | } 42 | return data; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/app/admintools/querry/mc/MinecraftPing.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 jamietech. All rights reserved. 3 | * https://github.com/jamietech/MinecraftServerPing 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are 6 | * permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, this list of 9 | * conditions and the following disclaimer. 10 | * 11 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list 12 | * of conditions and the following disclaimer in the documentation and/or other materials 13 | * provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR IMPLIED 16 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 17 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR 18 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 21 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 22 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 23 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | * 25 | * The views and conclusions contained in the software and documentation are those of the 26 | * authors and contributors and should not be interpreted as representing official policies, 27 | * either expressed or implied, of anybody else. 28 | */ 29 | package app.admintools.querry.mc; 30 | 31 | import java.io.ByteArrayOutputStream; 32 | import java.io.DataInputStream; 33 | import java.io.DataOutputStream; 34 | import java.io.IOException; 35 | import java.net.InetSocketAddress; 36 | import java.net.Socket; 37 | import com.google.gson.Gson; 38 | 39 | public class MinecraftPing { 40 | 41 | /** 42 | * Fetches a {@link MinecraftPingReply} for the supplied hostname. 43 | * Assumed timeout of 2s and port of 25565. 44 | * 45 | * @param hostname - a valid String hostname 46 | * @return {@link MinecraftPingReply} 47 | * @throws IOException 48 | */ 49 | public MinecraftPingReply getPing(final String hostname) throws IOException { 50 | return this.getPing(new MinecraftPingOptions().setHostname(hostname)); 51 | } 52 | 53 | /** 54 | * Fetches a {@link MinecraftPingReply} for the supplied options. 55 | * 56 | * @param options - a filled instance of {@link MinecraftPingOptions} 57 | * @return {@link MinecraftPingReply} 58 | * @throws IOException 59 | */ 60 | public MinecraftPingReply getPing(final MinecraftPingOptions options) throws IOException { 61 | MinecraftPingUtil.validate(options.getHostname(), "Hostname cannot be null."); 62 | MinecraftPingUtil.validate(options.getPort(), "Port cannot be null."); 63 | 64 | final Socket socket = new Socket(); 65 | socket.connect(new InetSocketAddress(options.getHostname(), options.getPort()), options.getTimeout()); 66 | 67 | final DataInputStream in = new DataInputStream(socket.getInputStream()); 68 | final DataOutputStream out = new DataOutputStream(socket.getOutputStream()); 69 | 70 | //> Handshake 71 | ByteArrayOutputStream handshake_bytes = new ByteArrayOutputStream(); 72 | DataOutputStream handshake = new DataOutputStream(handshake_bytes); 73 | 74 | handshake.writeByte(MinecraftPingUtil.PACKET_HANDSHAKE); 75 | MinecraftPingUtil.writeVarInt(handshake, MinecraftPingUtil.PROTOCOL_VERSION); 76 | MinecraftPingUtil.writeVarInt(handshake, options.getHostname().length()); 77 | handshake.writeBytes(options.getHostname()); 78 | handshake.writeShort(options.getPort()); 79 | MinecraftPingUtil.writeVarInt(handshake, MinecraftPingUtil.STATUS_HANDSHAKE); 80 | 81 | MinecraftPingUtil.writeVarInt(out, handshake_bytes.size()); 82 | out.write(handshake_bytes.toByteArray()); 83 | 84 | //> Status request 85 | out.writeByte(0x01); // Size of packet 86 | out.writeByte(MinecraftPingUtil.PACKET_STATUSREQUEST); 87 | 88 | //< Status response 89 | MinecraftPingUtil.readVarInt(in); // Size 90 | int id = MinecraftPingUtil.readVarInt(in); 91 | 92 | MinecraftPingUtil.io(id == -1, "Server prematurely ended stream."); 93 | MinecraftPingUtil.io(id != MinecraftPingUtil.PACKET_STATUSREQUEST, "Server returned invalid packet."); 94 | 95 | int length = MinecraftPingUtil.readVarInt(in); 96 | MinecraftPingUtil.io(length == -1, "Server prematurely ended stream."); 97 | MinecraftPingUtil.io(length == 0, "Server returned unexpected value."); 98 | 99 | byte[] data = new byte[length]; 100 | in.readFully(data); 101 | String json = new String(data, options.getCharset()); 102 | 103 | //> Ping 104 | out.writeByte(0x09); // Size of packet 105 | out.writeByte(MinecraftPingUtil.PACKET_PING); 106 | out.writeLong(System.currentTimeMillis()); 107 | 108 | //< Ping 109 | MinecraftPingUtil.readVarInt(in); // Size 110 | id = MinecraftPingUtil.readVarInt(in); 111 | MinecraftPingUtil.io(id == -1, "Server prematurely ended stream."); 112 | MinecraftPingUtil.io(id != MinecraftPingUtil.PACKET_PING, "Server returned invalid packet."); 113 | 114 | // Close 115 | handshake.close(); 116 | handshake_bytes.close(); 117 | out.close(); 118 | in.close(); 119 | socket.close(); 120 | 121 | return new Gson().fromJson(json, MinecraftPingReply.class); 122 | } 123 | 124 | } 125 | -------------------------------------------------------------------------------- /src/main/java/app/admintools/querry/mc/MinecraftPingOptions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 jamietech. All rights reserved. 3 | * https://github.com/jamietech/MinecraftServerPing 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are 6 | * permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, this list of 9 | * conditions and the following disclaimer. 10 | * 11 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list 12 | * of conditions and the following disclaimer in the documentation and/or other materials 13 | * provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR IMPLIED 16 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 17 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR 18 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 21 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 22 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 23 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | * 25 | * The views and conclusions contained in the software and documentation are those of the 26 | * authors and contributors and should not be interpreted as representing official policies, 27 | * either expressed or implied, of anybody else. 28 | */ 29 | package app.admintools.querry.mc; 30 | 31 | /** 32 | * Storage class for {@link MinecraftPing} options. 33 | */ 34 | public class MinecraftPingOptions { 35 | 36 | private String hostname; 37 | private int port = 25565; 38 | private int timeout = 2000; 39 | private String charset = "UTF-8"; 40 | 41 | public MinecraftPingOptions setHostname(String hostname) { 42 | this.hostname = hostname; 43 | return this; 44 | } 45 | 46 | public MinecraftPingOptions setPort(int port) { 47 | this.port = port; 48 | return this; 49 | } 50 | 51 | public MinecraftPingOptions setTimeout(int timeout) { 52 | this.timeout = timeout; 53 | return this; 54 | } 55 | 56 | public MinecraftPingOptions setCharset(String charset) { 57 | this.charset = charset; 58 | return this; 59 | } 60 | 61 | public String getHostname() { 62 | return this.hostname; 63 | } 64 | 65 | public int getPort() { 66 | return this.port; 67 | } 68 | 69 | public int getTimeout() { 70 | return this.timeout; 71 | } 72 | 73 | public String getCharset() { 74 | return this.charset; 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/app/admintools/querry/mc/MinecraftPingReply.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 jamietech. All rights reserved. 3 | * https://github.com/jamietech/MinecraftServerPing 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are 6 | * permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, this list of 9 | * conditions and the following disclaimer. 10 | * 11 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list 12 | * of conditions and the following disclaimer in the documentation and/or other materials 13 | * provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR IMPLIED 16 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 17 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR 18 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 21 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 22 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 23 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | * 25 | * The views and conclusions contained in the software and documentation are those of the 26 | * authors and contributors and should not be interpreted as representing official policies, 27 | * either expressed or implied, of anybody else. 28 | */ 29 | package app.admintools.querry.mc; 30 | 31 | import java.util.List; 32 | 33 | /** 34 | * References: http://wiki.vg/Server_List_Ping 35 | * https://gist.github.com/thinkofdeath/6927216 36 | */ 37 | public class MinecraftPingReply { 38 | 39 | private Description description; 40 | private Players players; 41 | private Version version; 42 | private String favicon; 43 | 44 | /** 45 | * @return the MOTD 46 | */ 47 | public Description getDescription() { 48 | return this.description; 49 | } 50 | 51 | /** 52 | * @return @{link Players} 53 | */ 54 | public Players getPlayers() { 55 | return this.players; 56 | } 57 | 58 | /** 59 | * @return @{link Version} 60 | */ 61 | public Version getVersion() { 62 | return this.version; 63 | } 64 | 65 | /** 66 | * @return Base64 encoded favicon image 67 | */ 68 | public String getFavicon() { 69 | return this.favicon; 70 | } 71 | 72 | public class Description { 73 | 74 | private String text; 75 | 76 | /** 77 | * @return Server description text 78 | */ 79 | public String getText() { 80 | return this.text; 81 | } 82 | } 83 | 84 | public class Players { 85 | 86 | private int max; 87 | private int online; 88 | private List sample; 89 | 90 | /** 91 | * @return Maximum player count 92 | */ 93 | public int getMax() { 94 | return this.max; 95 | } 96 | 97 | /** 98 | * @return Online player count 99 | */ 100 | public int getOnline() { 101 | return this.online; 102 | } 103 | 104 | /** 105 | * @return List of some players (if any) specified by server 106 | */ 107 | public List getSample() { 108 | return this.sample; 109 | } 110 | } 111 | 112 | public class Player { 113 | 114 | private String name; 115 | private String id; 116 | 117 | /** 118 | * @return Name of player 119 | */ 120 | public String getName() { 121 | return this.name; 122 | } 123 | 124 | /** 125 | * @return Unknown 126 | */ 127 | public String getId() { 128 | return this.id; 129 | } 130 | 131 | } 132 | 133 | public class Version { 134 | 135 | private String name; 136 | private int protocol; 137 | 138 | /** 139 | * @return Version name (ex: 13w41a) 140 | */ 141 | public String getName() { 142 | return this.name; 143 | } 144 | 145 | /** 146 | * @return Protocol version 147 | */ 148 | public int getProtocol() { 149 | return this.protocol; 150 | } 151 | } 152 | 153 | } 154 | -------------------------------------------------------------------------------- /src/main/java/app/admintools/querry/mc/MinecraftPingUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014 jamietech. All rights reserved. 3 | * https://github.com/jamietech/MinecraftServerPing 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are 6 | * permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, this list of 9 | * conditions and the following disclaimer. 10 | * 11 | * 2. Redistributions in binary form must reproduce the above copyright notice, this list 12 | * of conditions and the following disclaimer in the documentation and/or other materials 13 | * provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR IMPLIED 16 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 17 | * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR 18 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 21 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 22 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 23 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | * 25 | * The views and conclusions contained in the software and documentation are those of the 26 | * authors and contributors and should not be interpreted as representing official policies, 27 | * either expressed or implied, of anybody else. 28 | */ 29 | package app.admintools.querry.mc; 30 | 31 | import java.io.DataInputStream; 32 | import java.io.DataOutputStream; 33 | import java.io.IOException; 34 | 35 | public class MinecraftPingUtil { 36 | 37 | public static byte PACKET_HANDSHAKE = 0x00, PACKET_STATUSREQUEST = 0x00, 38 | PACKET_PING = 0x01; 39 | public static int PROTOCOL_VERSION = 4; 40 | public static int STATUS_HANDSHAKE = 1; 41 | 42 | public static void validate(final Object o, final String m) { 43 | if (o == null) { 44 | throw new RuntimeException(m); 45 | } 46 | } 47 | 48 | public static void io(final boolean b, final String m) throws IOException { 49 | if (b) { 50 | throw new IOException(m); 51 | } 52 | } 53 | 54 | /** 55 | * @author thinkofdeath See: 56 | * https://gist.github.com/thinkofdeath/e975ddee04e9c87faf22 57 | */ 58 | public static int readVarInt(DataInputStream in) throws IOException { 59 | int i = 0; 60 | int j = 0; 61 | while (true) { 62 | int k = in.readByte(); 63 | 64 | i |= (k & 0x7F) << j++ * 7; 65 | 66 | if (j > 5) { 67 | throw new RuntimeException("VarInt too big"); 68 | } 69 | 70 | if ((k & 0x80) != 128) { 71 | break; 72 | } 73 | } 74 | 75 | return i; 76 | } 77 | 78 | /** 79 | * @author thinkofdeath See: 80 | * https://gist.github.com/thinkofdeath/e975ddee04e9c87faf22 81 | * @throws IOException 82 | */ 83 | public static void writeVarInt(DataOutputStream out, int paramInt) throws IOException { 84 | while (true) { 85 | if ((paramInt & 0xFFFFFF80) == 0) { 86 | out.writeByte(paramInt); 87 | return; 88 | } 89 | 90 | out.writeByte(paramInt & 0x7F | 0x80); 91 | paramInt >>>= 7; 92 | } 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/app/admintools/querry/mc/QuerryUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package app.admintools.querry.mc; 7 | 8 | import java.io.ByteArrayInputStream; 9 | import java.io.InputStream; 10 | import java.util.Base64; 11 | import javafx.scene.image.Image; 12 | 13 | /** 14 | * 15 | * @author lukak 16 | */ 17 | public class QuerryUtils { 18 | 19 | public static Image convertToImage(String favicon) { 20 | favicon = favicon.split(",")[1]; 21 | InputStream in = Base64.getDecoder().wrap(new ByteArrayInputStream(favicon.getBytes())); 22 | return new Image(in); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/app/admintools/security/Mozaic.java: -------------------------------------------------------------------------------- 1 | package app.admintools.security; 2 | 3 | import java.io.File; 4 | import java.io.FileNotFoundException; 5 | import java.io.FileOutputStream; 6 | import java.io.IOException; 7 | import java.io.UnsupportedEncodingException; 8 | import java.nio.file.Files; 9 | import java.security.InvalidKeyException; 10 | import java.security.MessageDigest; 11 | import java.security.NoSuchAlgorithmException; 12 | import java.util.Random; 13 | import java.util.logging.Level; 14 | import java.util.logging.Logger; 15 | import javax.crypto.BadPaddingException; 16 | import javax.crypto.IllegalBlockSizeException; 17 | import javax.crypto.NoSuchPaddingException; 18 | 19 | /** 20 | * Mosaic algorithm for saving and writing encripred files 21 | * 22 | * @author lukak 23 | */ 24 | public class Mozaic { 25 | 26 | private final static String META_FILE_PATH = "meta.encdat"; 27 | private final static String DATA_FILE_PATH = "prop.encdat"; 28 | 29 | public static byte[] readMetaData() { 30 | try { 31 | return readBinary(META_FILE_PATH); 32 | } catch (IOException ex) { 33 | byte[] key = generateKey(); 34 | try { 35 | writeMetaData(key); 36 | } catch (IOException ex1) { 37 | 38 | } 39 | return key; 40 | } 41 | } 42 | 43 | public static void writeMetaData(byte[] data) throws IOException { 44 | writeBinary(META_FILE_PATH, data); 45 | } 46 | 47 | public static byte[] generateKey() { 48 | String protoKey = ""; 49 | for (int i = 0; i < 16; i++) { 50 | Random rand = new Random(); 51 | protoKey += rand.nextInt(10); 52 | } 53 | MessageDigest digest; 54 | try { 55 | digest = MessageDigest.getInstance("SHA-256"); 56 | return digest.digest(protoKey.getBytes()); 57 | } catch (NoSuchAlgorithmException ex) { 58 | Logger.getLogger(Mozaic.class.getName()).log(Level.SEVERE, null, ex); 59 | } 60 | return "0-sadwa546aAD4a87da3sAD".getBytes(); 61 | } 62 | 63 | public static String read() throws IOException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException { 64 | byte[] data = readBinary(DATA_FILE_PATH); 65 | 66 | SecureIO sec = new SecureIO(); 67 | 68 | data = sec.decrypt(data, readMetaData()); 69 | return new String(data); 70 | } 71 | 72 | public static void write(String propsToWrite) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException, IOException { 73 | SecureIO sec = new SecureIO(); 74 | 75 | writeBinary(DATA_FILE_PATH, sec.encrypt(propsToWrite.getBytes(), readMetaData())); 76 | } 77 | 78 | public static byte[] readBinary(String filePath) throws IOException { 79 | File file = new File(filePath); 80 | return Files.readAllBytes(file.toPath()); 81 | } 82 | 83 | public static void writeBinary(String filePath, byte[] data) throws FileNotFoundException, IOException { 84 | FileOutputStream fos = new FileOutputStream(filePath); 85 | fos.write(data); 86 | fos.close(); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/main/java/app/admintools/security/SecureIO.java: -------------------------------------------------------------------------------- 1 | package app.admintools.security; 2 | 3 | import java.io.UnsupportedEncodingException; 4 | import java.security.InvalidKeyException; 5 | import java.security.MessageDigest; 6 | import java.security.NoSuchAlgorithmException; 7 | import java.util.Arrays; 8 | import javax.crypto.BadPaddingException; 9 | import javax.crypto.Cipher; 10 | import javax.crypto.IllegalBlockSizeException; 11 | import javax.crypto.NoSuchPaddingException; 12 | import javax.crypto.spec.SecretKeySpec; 13 | 14 | /** 15 | * 16 | * @author lukak 17 | */ 18 | public class SecureIO { 19 | 20 | private SecretKeySpec secretKey; 21 | private byte[] key; 22 | 23 | public void setKey(byte[] myKey) { 24 | MessageDigest sha = null; 25 | try { 26 | key = myKey; 27 | sha = MessageDigest.getInstance("SHA-1"); 28 | key = sha.digest(key); 29 | key = Arrays.copyOf(key, 16); 30 | secretKey = new SecretKeySpec(key, "AES"); 31 | } catch (NoSuchAlgorithmException e) { 32 | 33 | } 34 | } 35 | 36 | public byte[] encrypt(byte[] data, byte[] secret) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException { 37 | setKey(secret); 38 | Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); 39 | cipher.init(Cipher.ENCRYPT_MODE, secretKey); 40 | return cipher.doFinal(data); 41 | } 42 | 43 | public byte[] decrypt(byte[] data, byte[] secret) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException { 44 | setKey(secret); 45 | Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING"); 46 | cipher.init(Cipher.DECRYPT_MODE, secretKey); 47 | return cipher.doFinal(data); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/app/admintools/security/credentials/Credentials.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package app.admintools.security.credentials; 7 | 8 | import java.io.IOException; 9 | import javafx.scene.layout.AnchorPane; 10 | import net.kronos.rkon.core.ex.AuthenticationException; 11 | import app.admintools.gui.credentials.credcard.CredCard; 12 | import app.admintools.util.CustomRcon; 13 | 14 | /** 15 | * 16 | * @author lukak 17 | */ 18 | public class Credentials { 19 | 20 | private String ip; 21 | private int port; 22 | private String password; 23 | private String name; 24 | private int pingPort; 25 | 26 | private Credentials() { 27 | } 28 | 29 | /** 30 | * Create a new Credentials instance 31 | * 32 | * @param ip Ip of server 33 | * @param port Port of server 34 | * @param password Password of server 35 | * @param name Name of server 36 | * @param pingPort Port to ping 37 | */ 38 | public Credentials(String ip, int port, String password, String name, int pingPort) { 39 | this.ip = ip; 40 | this.port = port; 41 | this.password = password; 42 | this.name = name; 43 | this.pingPort = pingPort; 44 | } 45 | 46 | /** 47 | * Get password. 48 | * 49 | * @return password 50 | */ 51 | public String getPassword() { 52 | return password; 53 | } 54 | 55 | /** 56 | * Get the port. 57 | * 58 | * @return Port 59 | */ 60 | public int getPort() { 61 | return port; 62 | } 63 | 64 | /** 65 | * Get IP. 66 | * 67 | * @return IP 68 | */ 69 | public String getIP() { 70 | return ip; 71 | } 72 | 73 | /** 74 | * Get the name of the credential. Used in title of CredCard. 75 | * 76 | * @return Name 77 | */ 78 | public String getName() { 79 | return name; 80 | } 81 | 82 | /** 83 | * Get the ping port. 84 | * 85 | * @return Port 86 | */ 87 | public int getPingPort() { 88 | return pingPort; 89 | } 90 | 91 | /** 92 | * Create a CredCard with the credentials 93 | * 94 | * @return CredCard AnchorPane 95 | */ 96 | public AnchorPane getCredCard() { 97 | return CredCard.createCredCard(name, ip + ":" + port, this); 98 | } 99 | 100 | /** 101 | * Creates a CustomRcon instance and refreshes the singleton 102 | * 103 | * @return CustomRcon instance 104 | * @throws IOException 105 | * @throws AuthenticationException 106 | */ 107 | public CustomRcon createRcon() throws IOException, AuthenticationException { 108 | return CustomRcon.getInstance(ip, port, password.getBytes()); 109 | } 110 | 111 | @Override 112 | public boolean equals(Object obj) { 113 | Credentials credcheck = (Credentials) obj; 114 | return ip.equals(credcheck.ip) && port == credcheck.port && password.equals(credcheck.password) && name.equals(credcheck.name); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/main/java/app/admintools/security/credentials/CredentialsIO.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package app.admintools.security.credentials; 7 | 8 | import com.google.gson.Gson; 9 | import com.google.gson.GsonBuilder; 10 | import com.google.gson.reflect.TypeToken; 11 | import java.io.File; 12 | import java.io.IOException; 13 | import java.io.Reader; 14 | import java.io.Writer; 15 | import java.nio.file.Files; 16 | import java.util.ArrayList; 17 | 18 | /** 19 | * 20 | * @author lukak 21 | */ 22 | public class CredentialsIO { 23 | 24 | public static final String PATH = "credentials.json"; 25 | 26 | public static ArrayList readCredentials() throws IOException { 27 | Reader reader = Files.newBufferedReader(new File(PATH).toPath()); 28 | 29 | ArrayList credentials = (ArrayList) new Gson().fromJson(reader, new TypeToken>() { 30 | }.getType()); 31 | 32 | reader.close(); 33 | 34 | return credentials; 35 | } 36 | 37 | public static void writeCredentials(ArrayList credentials) throws IOException { 38 | 39 | // create a writer 40 | Writer writer = Files.newBufferedWriter(new File(PATH).toPath()); 41 | 42 | //credentials = (ArrayList) gson.fromJson(reader, new TypeToken>() {}.getType()); 43 | new GsonBuilder().setPrettyPrinting().create().toJson(credentials, writer); 44 | 45 | // close writer 46 | writer.close(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/app/admintools/textprocessing/ChatColour.java: -------------------------------------------------------------------------------- 1 | package app.admintools.textprocessing; 2 | 3 | /** 4 | * 5 | * @author lukak 6 | */ 7 | public class ChatColour { 8 | 9 | //Chat colours. big thnx to https://www.digminecraft.com/lists/color_list_pc.php 10 | public static final String DARK_RED = "#AA0000"; 11 | public static final String RED = "#FF5555"; 12 | public static final String GOLD = "#FFAA00"; 13 | public static final String YELLOW = "#FFFF55"; 14 | public static final String DARK_GREEN = "#00AA00"; 15 | public static final String GREEN = "#55FF55"; 16 | public static final String AQUA = "#55FFFF"; 17 | public static final String DARK_AQUA = "#00AAAA"; 18 | public static final String DARK_BLUE = "#0000AA"; 19 | public static final String BLUE = "#5555FF"; 20 | public static final String LIGHT_PURPLE = "#FF55FF"; 21 | public static final String DARK_PURPLE = "#AA00AA"; 22 | public static final String WHITE = "#FFFFFF"; 23 | public static final String GRAY = "#AAAAAA"; 24 | public static final String DARK_GRAY = "#555555"; 25 | public static final String BLACK = "#000000"; 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/app/admintools/textprocessing/Markup.java: -------------------------------------------------------------------------------- 1 | package app.admintools.textprocessing; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.Random; 6 | 7 | /** 8 | * 9 | * @author lukak 10 | */ 11 | public class Markup { 12 | 13 | public static String generateMarkupParagraph(String text) { 14 | ArrayList strongArr = new ArrayList<>(); 15 | ArrayList splitText = new ArrayList<>(Arrays.asList(text.split("§"))); 16 | String lastColor = ChatColour.GRAY; 17 | if (splitText.size() == 1) { 18 | strongArr.add(getParagraphElement(splitText.get(0), ChatColour.GRAY, "normal", "none")); 19 | } else { 20 | //For every individualSplitText in splitText 21 | for (String inSplitText : splitText) { 22 | if (inSplitText.startsWith("0")) { 23 | //black 24 | strongArr.add(getParagraphElement(removeFirstChar(inSplitText), ChatColour.BLACK, "normal", "none")); 25 | lastColor = ChatColour.BLACK; 26 | } else if (inSplitText.startsWith("1")) { 27 | //dark blue 28 | strongArr.add(getParagraphElement(removeFirstChar(inSplitText), ChatColour.DARK_BLUE, "normal", "none")); 29 | lastColor = ChatColour.DARK_BLUE; 30 | } else if (inSplitText.startsWith("2")) { 31 | //dark green 32 | strongArr.add(getParagraphElement(removeFirstChar(inSplitText), ChatColour.DARK_GREEN, "normal", "none")); 33 | lastColor = ChatColour.DARK_GREEN; 34 | } else if (inSplitText.startsWith("3")) { 35 | //Dark Aqua 36 | strongArr.add(getParagraphElement(removeFirstChar(inSplitText), ChatColour.DARK_AQUA, "normal", "none")); 37 | lastColor = ChatColour.DARK_AQUA; 38 | } else if (inSplitText.startsWith("4")) { 39 | //Dark red 40 | strongArr.add(getParagraphElement(removeFirstChar(inSplitText), ChatColour.DARK_RED, "normal", "none")); 41 | lastColor = ChatColour.DARK_RED; 42 | } else if (inSplitText.startsWith("5")) { 43 | //Dark purple 44 | strongArr.add(getParagraphElement(removeFirstChar(inSplitText), ChatColour.DARK_PURPLE, "normal", "none")); 45 | lastColor = ChatColour.DARK_PURPLE; 46 | } else if (inSplitText.startsWith("6")) { 47 | //Gold 48 | strongArr.add(getParagraphElement(removeFirstChar(inSplitText), ChatColour.GOLD, "normal", "none")); 49 | lastColor = ChatColour.GOLD; 50 | } else if (inSplitText.startsWith("7")) { 51 | //Gray 52 | strongArr.add(getParagraphElement(removeFirstChar(inSplitText), ChatColour.GRAY, "normal", "none")); 53 | lastColor = ChatColour.GRAY; 54 | } else if (inSplitText.startsWith("8")) { 55 | //Dark gray 56 | strongArr.add(getParagraphElement(removeFirstChar(inSplitText), ChatColour.DARK_GRAY, "normal", "none")); 57 | lastColor = ChatColour.DARK_GRAY; 58 | } else if (inSplitText.startsWith("9")) { 59 | //Blue 60 | strongArr.add(getParagraphElement(removeFirstChar(inSplitText), ChatColour.BLUE, "normal", "none")); 61 | lastColor = ChatColour.BLUE; 62 | } else if (inSplitText.startsWith("a")) { 63 | //Green 64 | strongArr.add(getParagraphElement(removeFirstChar(inSplitText), ChatColour.GREEN, "normal", "none")); 65 | lastColor = ChatColour.GREEN; 66 | } else if (inSplitText.startsWith("b")) { 67 | //Aqua 68 | strongArr.add(getParagraphElement(removeFirstChar(inSplitText), ChatColour.AQUA, "normal", "none")); 69 | lastColor = ChatColour.AQUA; 70 | } else if (inSplitText.startsWith("c")) { 71 | //Red 72 | strongArr.add(getParagraphElement(removeFirstChar(inSplitText), ChatColour.RED, "normal", "none")); 73 | lastColor = ChatColour.RED; 74 | } else if (inSplitText.startsWith("d")) { 75 | //Light purple 76 | strongArr.add(getParagraphElement(removeFirstChar(inSplitText), ChatColour.LIGHT_PURPLE, "normal", "none")); 77 | lastColor = ChatColour.LIGHT_PURPLE; 78 | } else if (inSplitText.startsWith("e")) { 79 | //Yellow 80 | strongArr.add(getParagraphElement(removeFirstChar(inSplitText), ChatColour.YELLOW, "normal", "none")); 81 | lastColor = ChatColour.YELLOW; 82 | } else if (inSplitText.startsWith("f")) { 83 | //White 84 | strongArr.add(getParagraphElement(removeFirstChar(inSplitText), ChatColour.WHITE, "normal", "none")); 85 | lastColor = ChatColour.WHITE; 86 | } else if (inSplitText.startsWith("k")) { 87 | //obfuscated 88 | int leftLimit = 97; // letter 'a' 89 | int rightLimit = 122; // letter 'z' 90 | Random random = new Random(); 91 | 92 | String generatedText = random.ints(leftLimit, rightLimit + 1) 93 | .limit(inSplitText.length()) //limit the lengh to the lengh of the source string 94 | .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append) 95 | .toString(); 96 | 97 | strongArr.add(getParagraphElement(inSplitText, lastColor, "normal", "none")); 98 | } else if (inSplitText.startsWith("l")) { 99 | //bold 100 | strongArr.add(getParagraphElement(removeFirstChar(inSplitText), lastColor, "bold", "none")); 101 | } else if (inSplitText.startsWith("m")) { 102 | //strikethroug 103 | strongArr.add(getParagraphElement(removeFirstChar(inSplitText), lastColor, "normal", "line-through")); 104 | } else if (inSplitText.startsWith("n")) { 105 | //underline 106 | strongArr.add(getParagraphElement(removeFirstChar(inSplitText), lastColor, "normal", "underline")); 107 | } else if (inSplitText.startsWith("o")) { 108 | //italic 109 | strongArr.add("" + text + ""); 110 | } else if (inSplitText.startsWith("r")) { //Proveriti u slucaju greske 111 | //reset 112 | lastColor = ChatColour.GRAY; 113 | strongArr.add(getParagraphElement(removeFirstChar(inSplitText), ChatColour.GRAY, "normal", "none")); 114 | } else { 115 | lastColor = ChatColour.GRAY; 116 | strongArr.add(getParagraphElement(inSplitText, ChatColour.GRAY, "normal", "none")); 117 | } 118 | } 119 | } 120 | //After the md is done , we can assemble the paragraph 121 | //DebugMD - strongArr.add(text); 122 | String paragraph = "

"; 123 | for (String strong : strongArr) { 124 | paragraph += strong; 125 | } 126 | paragraph += "

"; 127 | return paragraph.replace("\n", "
"); 128 | } 129 | 130 | private static String removeFirstChar(String s) { 131 | return s.substring(1); 132 | } 133 | 134 | private static String getParagraphElement(String text, String color, String fontWeight, String textDecoration) { 135 | return "" + text + ""; 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/main/java/app/admintools/textprocessing/TellrawFormatter.java: -------------------------------------------------------------------------------- 1 | package app.admintools.textprocessing; 2 | 3 | /** 4 | * 5 | * @author lukak 6 | */ 7 | public class TellrawFormatter { 8 | 9 | public static String assembleSimpleTellraw(String message) { 10 | return "tellraw @a [\"\",{\"text\":\"[Admin Tools]\",\"color\":\"#00FF82\"},{\"text\":\" " + message + "\",\"color\":\"#E1E1E1\"},{\"text\":\" \"}]"; 11 | } 12 | 13 | public static String assembleLoginTellraw(String username) { 14 | return "tellraw @a [\"\",{\"text\":\"[Admin Tools] \",\"color\":\"#00FF82\"},{\"text\":\"" + username + " \",\"color\":\"aqua\"},{\"text\":\"logged in\",\"color\":\"#E1E1E1\"}]"; 15 | } 16 | 17 | public static String assembleLogoutTellraw(String username) { 18 | return "tellraw @a [\"\",{\"text\":\"[Admin Tools] \",\"color\":\"#00FF82\"},{\"text\":\"" + username + " \",\"color\":\"aqua\"},{\"text\":\"logged out\",\"color\":\"#E1E1E1\"}]"; 19 | } 20 | 21 | public static String assembleSayTellraw(String username, String message) { 22 | return "tellraw @a [\"\",{\"text\":\"[Admin Tools] \",\"color\":\"#00FF82\"},{\"text\":\"" + username + " \",\"color\":\"aqua\"},{\"text\":\"said : " + message + "\",\"color\":\"#E1E1E1\"}]"; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/app/admintools/threadmanager/ThreadManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package app.admintools.threadmanager; 7 | 8 | import java.util.ArrayList; 9 | 10 | /** 11 | * 12 | * @author lukak 13 | */ 14 | public class ThreadManager { 15 | 16 | private static ArrayList singleThreadPool = new ArrayList(); 17 | 18 | /** 19 | * Managed starting of threads. Beware worker thread management uses names 20 | * 21 | * @param thread Thread that is going to be started. 22 | * @param type Type of thread. If the ThreadType is WORKER the thread 23 | * will be started only if its the only thread of its type in the 24 | * application, and if its ThreadType is ASYNCJOB then it starts 25 | * anyways. 26 | * @return If the thread has been started 27 | */ 28 | public static boolean startThread(Thread thread, ThreadType type) { 29 | if (type == ThreadType.WORKER) { 30 | if (!singleThreadPool.contains(thread.getName())) { 31 | singleThreadPool.add(thread.getName()); 32 | thread.start(); 33 | System.out.println("Started thread " + thread.getName()); 34 | return true; 35 | } 36 | return false; 37 | } 38 | if (type == ThreadType.ASYNCJOB) { 39 | thread.start(); 40 | return true; 41 | } 42 | return false; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/app/admintools/threadmanager/ThreadType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package app.admintools.threadmanager; 7 | 8 | /** 9 | * 10 | * @author lukak 11 | */ 12 | public enum ThreadType { 13 | WORKER, 14 | ASYNCJOB 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/app/admintools/util/AtLogger.java: -------------------------------------------------------------------------------- 1 | package app.admintools.util; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.util.Arrays; 7 | import java.util.Objects; 8 | import java.util.logging.Level; 9 | import java.util.logging.LogManager; 10 | import java.util.logging.Logger; 11 | 12 | /** 13 | * 14 | * @author lukak 15 | */ 16 | public class AtLogger { 17 | public static Logger logger = null; 18 | 19 | public static void init(){ 20 | if(logger == null){ 21 | try { 22 | //%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS %4$s %2$s %5$s%6$s%n 23 | //"[%1$tF %1$tT] [%6$-10s] [%4$-7s] %5$s %n" 24 | System.setProperty("java.util.logging.SimpleFormatter.format", "[%1$tF %1$tT] (%2$s) [%4$-7s] %5$s %n"); 25 | LogManager.getLogManager().readConfiguration(); 26 | } catch (IOException e) { 27 | e.printStackTrace(); 28 | } 29 | logger = Logger.getLogger(AtLogger.class.getName()); 30 | } 31 | } 32 | 33 | public static String formatException(Exception ex){ 34 | return ex.getClass().getName() + " : " + ex.getMessage(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/app/admintools/util/CustomRcon.java: -------------------------------------------------------------------------------- 1 | package app.admintools.util; 2 | 3 | import java.io.IOException; 4 | import java.net.Socket; 5 | import java.nio.charset.StandardCharsets; 6 | 7 | import net.kronos.rkon.core.Rcon; 8 | import net.kronos.rkon.core.ex.AuthenticationException; 9 | import app.admintools.textprocessing.TellrawFormatter; 10 | 11 | public class CustomRcon extends Rcon { 12 | 13 | private static CustomRcon instance; 14 | 15 | private CustomRcon(String host, int port, byte[] password) throws IOException, AuthenticationException { 16 | super(host, port, password); 17 | } 18 | 19 | public static CustomRcon getInstance() throws IOException, AuthenticationException { 20 | if (instance == null) { 21 | //Variable declaration 22 | Data data = Data.getInstance(); 23 | String host = data.getSelectedCredentials().getIP(); 24 | int port = data.getSelectedCredentials().getPort(); 25 | byte[] password = data.getSelectedCredentials().getPassword().getBytes(StandardCharsets.UTF_8); 26 | 27 | //Reading configuration from file 28 | //Constructing the instance 29 | instance = new CustomRcon(host, port, password); 30 | } 31 | //Returns the instance 32 | return instance; 33 | } 34 | 35 | public static CustomRcon getInstance(String host, int port, byte[] password) throws IOException, AuthenticationException { 36 | instance = null; 37 | instance = new CustomRcon(host, port, password); 38 | return instance; 39 | } 40 | 41 | public static void setToNull(){ 42 | instance = null; 43 | } 44 | 45 | //Short-circuit evaluation 46 | private static boolean empty(final String s) { 47 | return s == null || s.trim().isEmpty(); 48 | } 49 | 50 | @Override 51 | public String command(String payload) throws IOException { 52 | String uc = "Unknown command"; 53 | Data data = Data.getInstance(); 54 | if (!empty(payload)) { 55 | if (data.getMessageOverwriteSay()) { 56 | if (payload.split(" ")[0].equals("say")) { 57 | payload = TellrawFormatter.assembleSayTellraw(data.getMessageUsername(), payload.substring(payload.indexOf(" ") + 1)); 58 | } 59 | } 60 | String response = super.command(payload); 61 | if (empty(response)) { 62 | return "No command response"; 63 | } 64 | if (response.startsWith(uc)) { 65 | return uc; 66 | } 67 | return response; 68 | } 69 | return uc; 70 | } 71 | 72 | @Override 73 | public String toString() { 74 | Socket s = getSocket(); 75 | return s.getInetAddress() + ":" + s.getPort(); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/app/admintools/util/DRPC.java: -------------------------------------------------------------------------------- 1 | package app.admintools.util; 2 | 3 | import net.arikia.dev.drpc.DiscordEventHandlers; 4 | import net.arikia.dev.drpc.DiscordRPC; 5 | import net.arikia.dev.drpc.DiscordRichPresence; 6 | 7 | public class DRPC { 8 | /** 9 | * Initialise the discord rich presence. 10 | */ 11 | public static void initialise(){ 12 | DiscordEventHandlers handlers = new DiscordEventHandlers.Builder().setReadyEventHandler((user) -> { 13 | AtLogger.logger.info( "Connected to discord rpc as " + user.username + ":" + user.discriminator); 14 | }).build(); 15 | DiscordRPC.discordInitialize("790613792702726185", handlers ,true); 16 | DiscordRPC.discordRegister("790613792702726185", ""); 17 | DiscordRPC.discordRunCallbacks(); 18 | DiscordRichPresence rich = new DiscordRichPresence.Builder("In home").setDetails("").setStartTimestamps(System.currentTimeMillis()).setBigImage("default", "AdminTools release " + Version.getInstance().getStrippedVersion()).build(); 19 | DiscordRPC.discordUpdatePresence(rich); 20 | } 21 | 22 | /** 23 | * Update the discord rich presence status. 24 | * @param richPresence The next rich presence. 25 | */ 26 | public static void updateStatus(DiscordRichPresence richPresence){ 27 | DiscordRPC.discordUpdatePresence(richPresence); 28 | AtLogger.logger.info("Updated status : " + richPresence.details); 29 | } 30 | 31 | /** 32 | * Simple generation of a instance of DiscordRichPresence. 33 | * @param state The current state of the user for example In Home. 34 | * @param details More details. 35 | * @return A instance of DiscordRichPresence. 36 | */ 37 | public static DiscordRichPresence generatePresence(String state, String details){ 38 | String bigImage; 39 | if(Version.getInstance().isDevelopmentVersion()){ 40 | bigImage = "dev"; 41 | }else { 42 | bigImage = "default"; 43 | } 44 | return new DiscordRichPresence.Builder(state).setDetails(details).setStartTimestamps(System.currentTimeMillis()).setBigImage(bigImage, "AdminTools release " + Version.getInstance().getStrippedVersion()).build(); 45 | } 46 | 47 | /** 48 | * Simple generation of a instance of DiscordRichPresence. 49 | * @param state The current state of the user for example In Home. 50 | * @return A instance of DiscordRichPresence. 51 | */ 52 | public static DiscordRichPresence generatePresence(String state){ 53 | return generatePresence(state, ""); 54 | } 55 | 56 | public static void statusManagingServer() { 57 | DRPC.updateStatus(DRPC.generatePresence("Managing server")); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/app/admintools/util/Data.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package app.admintools.util; 7 | 8 | import java.io.File; 9 | import java.io.FileInputStream; 10 | import java.io.FileNotFoundException; 11 | import java.io.FileOutputStream; 12 | import java.io.IOException; 13 | import java.io.InputStream; 14 | import java.io.OutputStream; 15 | import java.lang.module.ModuleDescriptor; 16 | import java.util.ArrayList; 17 | import java.util.Arrays; 18 | import java.util.HashMap; 19 | import java.util.Properties; 20 | import app.admintools.security.credentials.Credentials; 21 | 22 | /** 23 | * 24 | * @author lukak 25 | */ 26 | public class Data { 27 | //All the variables 28 | 29 | static File config = new File("admintools.properties"); 30 | 31 | //public data 32 | /** 33 | * Java arguments 34 | */ 35 | public static String[] arguments = new String[1]; 36 | /** 37 | * Text and contents from the webview 38 | */ 39 | public static ArrayList rconTextData = null; 40 | 41 | //Used in rconWindow to get if its starting up 42 | //In versions >5.0.0 it is used to indicate if the selected credentials have changed 43 | public static boolean startingUp = true; 44 | 45 | /** 46 | * Is the view on the status window 47 | * Used in stopping and starting tick threads in the status window 48 | */ 49 | public static boolean isOnStatusWindow = false; 50 | 51 | /** 52 | * Selected credentials 53 | */ 54 | private static Credentials credentials = null; 55 | 56 | private static final String VERSION = "7.0.0.0.0"; 57 | 58 | //Singleton 59 | private static Data instance = null; 60 | 61 | private Data() { 62 | if (!config.exists()) { 63 | try { 64 | write(DataType.RCON_REMEMBER, defaults.get(DataType.RCON_REMEMBER)); 65 | write(DataType.QUERRY_API_REFRESHRATE, defaults.get(DataType.QUERRY_API_REFRESHRATE)); 66 | write(DataType.QUERRY_MC_REFRESHRATE, defaults.get(DataType.QUERRY_MC_REFRESHRATE)); 67 | write(DataType.MESSAGE_SEND_ON_LOGON, defaults.get(DataType.MESSAGE_SEND_ON_LOGON)); 68 | write(DataType.MESSAGE_OVERWRITE_SAY, defaults.get(DataType.MESSAGE_OVERWRITE_SAY)); 69 | write(DataType.USERNAME, defaults.get(DataType.USERNAME)); 70 | write(DataType.THEME, defaults.get(DataType.THEME)); 71 | } catch (IOException e) { 72 | AtLogger.logger.severe(AtLogger.formatException(e)); 73 | } 74 | } 75 | } 76 | 77 | /** 78 | * Gets the instance of DATA 79 | * 80 | * @return instance of DATA 81 | */ 82 | public static Data getInstance() { 83 | if (instance == null) { 84 | instance = new Data(); 85 | } 86 | return instance; 87 | } 88 | 89 | /** 90 | * Refreshes Data instance 91 | * 92 | * @return Data instanceaa 93 | */ 94 | public static Data refresh() { 95 | instance = new Data(); 96 | return instance; 97 | } 98 | 99 | /** 100 | * Gets the stored selected credentials 101 | * @return Credentials instance 102 | */ 103 | public Credentials getSelectedCredentials(){ 104 | return credentials; 105 | } 106 | 107 | /** 108 | * 109 | * @param creds 110 | */ 111 | public static void setSelectedCredentials(Credentials creds){ 112 | credentials = creds; 113 | startingUp = true; //Sets starting up to true to indicate to the rconWindow that stuff has changed 114 | } 115 | 116 | 117 | /** 118 | * Gets remember property 119 | * 120 | * @return remember property 121 | */ 122 | public boolean getRconRemember() throws IOException { 123 | return Boolean.parseBoolean(read(DataType.RCON_REMEMBER)); 124 | } 125 | 126 | /** 127 | * Gets the refresh rate for mc serv querry 128 | * 129 | * @return refresh rate 130 | */ 131 | public int getQuerryMcRefreshRate() throws IOException { 132 | return Integer.parseInt(read(DataType.QUERRY_MC_REFRESHRATE)); 133 | } 134 | 135 | /** 136 | * Gets refresh rate for Mojang API 137 | * 138 | * @return refresh rate 139 | */ 140 | public double getQuerryMojangApiRefreshRate() throws IOException { 141 | return Double.parseDouble(read(DataType.QUERRY_API_REFRESHRATE)); 142 | } 143 | 144 | public boolean getMessageNotify() throws IOException { 145 | return Boolean.parseBoolean(read(DataType.MESSAGE_SEND_ON_LOGON)); 146 | } 147 | 148 | public boolean getMessageOverwriteSay() throws IOException { 149 | return Boolean.parseBoolean(read(DataType.MESSAGE_OVERWRITE_SAY)); 150 | } 151 | 152 | public String getMessageUsername() throws IOException { 153 | return read(DataType.USERNAME); 154 | } 155 | 156 | public String getSelectedTheme() throws IOException { 157 | return read(DataType.THEME); 158 | } 159 | /** 160 | * Default valiues for the properties 161 | * "false", "10", "100", "false", "false", "username", "Default" 162 | */ 163 | public static HashMap defaults = new HashMap<>(){{ 164 | put(DataType.RCON_REMEMBER, "false"); 165 | put(DataType.QUERRY_MC_REFRESHRATE, "10"); 166 | put(DataType.QUERRY_API_REFRESHRATE, "100"); 167 | put(DataType.MESSAGE_SEND_ON_LOGON, "false"); 168 | put(DataType.MESSAGE_OVERWRITE_SAY, "false"); 169 | put(DataType.USERNAME, "username"); 170 | put(DataType.THEME, "default"); 171 | }}; 172 | 173 | /** 174 | * Writes the properties to disk 175 | * 176 | * @param key Key 177 | * @param value The valiue to write 178 | */ 179 | public static void write(String key, String value) throws IOException { 180 | Properties prop = new Properties(); 181 | OutputStream output = new FileOutputStream(config); 182 | prop.setProperty(key, value); 183 | prop.store(output, "AdminTools properties" + System.lineSeparator() + "Created by: LukeOnuke - https://github.com/LukeOnuke"); 184 | } 185 | 186 | /** 187 | * Reads the properties from disk 188 | * 189 | * @return ArrayList of properites 190 | */ 191 | public static String read(String key) throws IOException { 192 | Properties prop = new Properties(); 193 | InputStream input = new FileInputStream(config); 194 | prop.load(input); 195 | return prop.getProperty(key, defaults.get(key)); 196 | } 197 | } 198 | -------------------------------------------------------------------------------- /src/main/java/app/admintools/util/DataType.java: -------------------------------------------------------------------------------- 1 | package app.admintools.util; 2 | 3 | public class DataType { 4 | public static final String RCON_REMEMBER = "rcon.remember"; 5 | public static final String QUERRY_MC_REFRESHRATE = "querry.mc.refreshrate"; 6 | public static final String QUERRY_API_REFRESHRATE = "querry.api.mojang.refreshrate"; 7 | public static final String MESSAGE_SEND_ON_LOGON = "message.send.on.login"; 8 | public static final String MESSAGE_OVERWRITE_SAY = "message.overwrite.say"; 9 | public static final String USERNAME = "message.username"; 10 | public static final String THEME = "theme.selected"; 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/app/admintools/util/Utill.java: -------------------------------------------------------------------------------- 1 | package app.admintools.util; 2 | 3 | import javafx.scene.Parent; 4 | import javafx.scene.Scene; 5 | import javafx.scene.layout.AnchorPane; 6 | import org.apache.commons.lang3.SystemUtils; 7 | 8 | import java.io.BufferedReader; 9 | import java.io.File; 10 | import java.io.IOException; 11 | import java.io.InputStreamReader; 12 | import java.net.HttpURLConnection; 13 | import java.net.URL; 14 | import java.text.SimpleDateFormat; 15 | import java.util.Date; 16 | 17 | /** 18 | * 19 | * @author lukak 20 | */ 21 | public class Utill { 22 | 23 | public static String getDate() { 24 | SimpleDateFormat sd = new SimpleDateFormat("[HH:mm:ss] "); 25 | return sd.format(new Date()); 26 | } 27 | 28 | /** 29 | * Gets responce of GET request sent to a url 30 | * 31 | * @param getUrl The url of the server to witch we send the GET request 32 | * @return String of what the servers responce was to the get request 33 | * @throws IOException When there is a IO error 34 | */ 35 | public static String getHTTPRequest(String getUrl) throws IOException { 36 | URL obj = new URL(getUrl); 37 | HttpURLConnection con = (HttpURLConnection) obj.openConnection(); //create HTTP connection 38 | con.setRequestMethod("GET"); //Send get request 39 | 40 | int responseCode = con.getResponseCode(); //responce code 41 | if (responseCode == HttpURLConnection.HTTP_OK) { // success 42 | BufferedReader in = new BufferedReader(new InputStreamReader( 43 | con.getInputStream())); 44 | String inputLine; 45 | StringBuffer response = new StringBuffer(); 46 | 47 | while ((inputLine = in.readLine()) != null) { 48 | response.append(inputLine); 49 | } 50 | in.close(); 51 | 52 | //return the results lol 53 | return response.toString(); 54 | } else { 55 | throw new IOException(); 56 | } 57 | } 58 | 59 | public static String removeSpigotFormatting(String commandReply) { 60 | commandReply = commandReply.replaceAll("[§][1-9a-zA-Z]", ""); //remove numbers and letters 61 | 62 | return commandReply; 63 | } 64 | 65 | public static void exit(int code) { 66 | System.exit(code); 67 | } 68 | 69 | /** 70 | * https://stackoverflow.com/questions/924394/how-to-get-the-filename-without-the-extension-in-java 71 | * @param str 72 | * @return 73 | */ 74 | public static String stripExtension (String str) { 75 | // Handle null case specially. 76 | 77 | if (str == null) return null; 78 | 79 | // Get position of last '.'. 80 | 81 | int pos = str.lastIndexOf("."); 82 | 83 | // If there wasn't any '.' just return the string as is. 84 | 85 | if (pos == -1) return str; 86 | 87 | // Otherwise return the string, up to the dot. 88 | 89 | return str.substring(0, pos); 90 | } 91 | 92 | public static String removeArrrayFormatting(String string){ 93 | return string.replace(",", "").replace("[", "").replace("]", ""); 94 | } 95 | 96 | public static String getPath(String path){ 97 | if(SystemUtils.IS_OS_WINDOWS){ 98 | return path.replace("\\", "/"); 99 | } 100 | return path.replace("\\", File.separator).replace("/", File.separator); 101 | 102 | } 103 | 104 | public static void setSelectedTheme(AnchorPane anchorPane){ 105 | try { 106 | anchorPane.getStylesheets().add(Utill.getPath("file:assets/themes/" + Data.getInstance().getSelectedTheme() + "/style.css")); 107 | } catch (IOException e) { 108 | AtLogger.logger.severe(AtLogger.formatException(e)); 109 | } 110 | } 111 | 112 | public static void setSelectedTheme(Parent root){ 113 | try { 114 | root.getStylesheets().add(Utill.getPath("file:assets/themes/" + Data.getInstance().getSelectedTheme() + "/style.css")); 115 | } catch (IOException e) { 116 | AtLogger.logger.severe(AtLogger.formatException(e)); 117 | } 118 | } 119 | 120 | public static void setSelectedTheme(Scene scene){ 121 | try { 122 | scene.getStylesheets().add(Utill.getPath("file:assets/themes/" + Data.getInstance().getSelectedTheme() + "/style.css")); 123 | } catch (IOException e) { 124 | AtLogger.logger.severe(AtLogger.formatException(e)); 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/main/java/app/admintools/util/Version.java: -------------------------------------------------------------------------------- 1 | package app.admintools.util; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.concurrent.atomic.AtomicInteger; 6 | 7 | public class Version { 8 | private final String VERSION_NUMBER = "7.1.0"; 9 | /** 10 | * Snapshot version, only used if isDevelopmentVersion is true 11 | * 12 | * Version number goes like 23d12m2020y001v . So its [Day Of Release]d[Month Of Release]m[Year Of Release]y[Snapshot Number]v 13 | */ 14 | private final String SNAPSHOT_VER = "17d3m2022y000v"; 15 | private final boolean isDevelopmentVersion = false; 16 | private static Version instance = null; 17 | 18 | public static Version getInstance() { 19 | if(instance == null){ 20 | instance = new Version(); 21 | } 22 | return instance; 23 | } 24 | 25 | public String getStrippedVersion(){ 26 | return VERSION_NUMBER.substring(0, 5); 27 | } 28 | 29 | public boolean isDevelopmentVersion() { 30 | return isDevelopmentVersion; 31 | } 32 | 33 | public String getSnapshotVersion() { 34 | return SNAPSHOT_VER; 35 | } 36 | 37 | public String getFullVersionNumber() { 38 | return VERSION_NUMBER; 39 | } 40 | 41 | public static int getVersionAsInt(String versionNumber){ 42 | versionNumber = versionNumber.replace("v", ""); 43 | ArrayList splitVer = new ArrayList<>(Arrays.asList(versionNumber.split("[.]"))); 44 | final AtomicInteger multiplier = new AtomicInteger(10000); 45 | final AtomicInteger result = new AtomicInteger(0); 46 | splitVer.forEach((verSegment) -> { 47 | result.getAndAdd(Integer.parseInt(verSegment) * multiplier.get()); 48 | multiplier.set(multiplier.get() / 10); 49 | }); 50 | return result.get(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/app/admintools/util/WindowLoader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package app.admintools.util; 7 | 8 | import java.io.IOException; 9 | 10 | import app.admintools.gui.splash.SplashScreen; 11 | import javafx.animation.FadeTransition; 12 | import javafx.fxml.FXMLLoader; 13 | import javafx.scene.Scene; 14 | import javafx.scene.layout.AnchorPane; 15 | import javafx.stage.Stage; 16 | import javafx.util.Duration; 17 | import app.admintools.gui.SettingsWindowController; 18 | 19 | /** 20 | * 21 | * @author lukak 22 | */ 23 | public class WindowLoader { 24 | 25 | public static void loadRcon(AnchorPane rootPane) { 26 | loadWindow(rootPane, Utill.getPath("/gui/fxml/RconWindow.fxml")); 27 | Data.isOnStatusWindow = false; 28 | } 29 | 30 | public static void loadSettings(AnchorPane rootPane) { 31 | loadWindow(rootPane, Utill.getPath("/gui/fxml/SettingsWindow.fxml")); 32 | Data.isOnStatusWindow = false; 33 | } 34 | 35 | public static void loadStatus(AnchorPane rootPane) { 36 | Data.isOnStatusWindow = true; 37 | loadWindow(rootPane, Utill.getPath("/gui/fxml/StatusWindow.fxml")); 38 | } 39 | 40 | public static void loadHome(AnchorPane rootPane) { 41 | loadWindow(rootPane, Utill.getPath("/gui/fxml/HomeWindow.fxml")); 42 | Data.isOnStatusWindow = false; 43 | } 44 | 45 | private static void loadWindow(AnchorPane rootPane, String url) { 46 | 47 | try { 48 | Data d = Data.getInstance(); //Get instance of data 49 | 50 | AnchorPane ap = FXMLLoader.load(SettingsWindowController.class.getResource(url)); //Get anchorpane 51 | 52 | //Set style for selected theme 53 | Utill.setSelectedTheme(ap); 54 | 55 | //Create stage yes 56 | Scene scene2 = new Scene(ap); 57 | Stage windowStage = (Stage) rootPane.getScene().getWindow(); 58 | //Get widht and height 59 | double width = windowStage.getWidth(); 60 | double height = windowStage.getHeight(); 61 | 62 | //Swich scene 63 | windowStage.setScene(scene2); 64 | 65 | //Get fade transition inbetween windows 66 | //Fade in 67 | //Foreach just netben 68 | ap.getChildren().stream().map((child) -> new FadeTransition(Duration.seconds(0.25), child)).map((ft) -> { 69 | ft.setFromValue(.3d); 70 | return ft; 71 | }).map((ft) -> { 72 | ft.setToValue(1.0d); 73 | return ft; 74 | }).forEachOrdered((ft) -> { 75 | ft.play(); 76 | }); 77 | 78 | //Refresh title 79 | windowStage.setTitle("Admin Tools - " + d.getSelectedCredentials().getIP() + ":" + d.getSelectedCredentials().getPort()); 80 | 81 | //Set width after scene swithch 82 | windowStage.setWidth(width); 83 | windowStage.setHeight(height); 84 | 85 | } catch (IOException ex) { 86 | AtLogger.logger.warning(AtLogger.formatException(ex)); 87 | } 88 | 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/main/resources/gui/fxml/HomeWindow.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /src/main/resources/gui/fxml/RconWindow.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 18 | 19 | 20 | 21 | 22 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /src/main/resources/gui/fxml/SettingsWindow.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /src/main/resources/gui/fxml/StatusWindow.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /src/main/resources/img/icon-baked.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LukeOnuke/AdminTools/0c7fb6b85a304d9966b64568d306b3c8b1afb184/src/main/resources/img/icon-baked.ico -------------------------------------------------------------------------------- /src/main/resources/img/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LukeOnuke/AdminTools/0c7fb6b85a304d9966b64568d306b3c8b1afb184/src/main/resources/img/icon.png -------------------------------------------------------------------------------- /src/main/resources/img/unknown-server.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LukeOnuke/AdminTools/0c7fb6b85a304d9966b64568d306b3c8b1afb184/src/main/resources/img/unknown-server.png --------------------------------------------------------------------------------