├── .gitignore ├── LICENSE ├── README.md ├── build.gradle ├── classmap-generator ├── Makefile ├── README └── src │ └── main.cpp ├── docs ├── button.md ├── chat.md ├── clear.md ├── click.md ├── close.md ├── cmdutils.md ├── desync.md ├── drop.md ├── help.md ├── leave.md ├── loop.md ├── mcfw.md ├── menuinfo.md ├── restoregui.md ├── rpack.md ├── savegui.md ├── session.md ├── swing.md ├── trade.md └── wake.md ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── src └── main ├── java └── org │ └── cmdutils │ ├── MainClient.java │ ├── ModInfo.java │ ├── command │ ├── Command.java │ ├── CommandEnvironment.java │ ├── CommandParser.java │ ├── Commands.java │ ├── RunnableCommand.java │ └── commands │ │ ├── BashCommand.java │ │ ├── ButtonCommand.java │ │ ├── ChatCommand.java │ │ ├── ClearCommand.java │ │ ├── ClickCommand.java │ │ ├── CloseCommand.java │ │ ├── CmdUtilsCommand.java │ │ ├── CrashCommand.java │ │ ├── DeSyncCommand.java │ │ ├── DropCommand.java │ │ ├── HelpCommand.java │ │ ├── LeaveCommand.java │ │ ├── LoopCommand.java │ │ ├── McfwCommand.java │ │ ├── MenuInfoCommand.java │ │ ├── RPackCommand.java │ │ ├── RestoreGuiCommand.java │ │ ├── SaveGuiCommand.java │ │ ├── SessionCommand.java │ │ ├── SlashCommand.java │ │ ├── SwingCommand.java │ │ ├── TradeCommand.java │ │ └── WakeCommand.java │ ├── mixin │ ├── ClientConnectionMixin.java │ ├── ScreenMixin.java │ └── accessor │ │ └── SessionAccessor.java │ ├── terminal │ ├── gui │ │ ├── InGameTerminalGui.java │ │ └── TerminalGui.java │ ├── logger │ │ ├── InGameLogger.java │ │ ├── Logger.java │ │ ├── NullLogger.java │ │ ├── TelnetLogger.java │ │ └── TextAreaLogger.java │ └── telnet │ │ └── TelnetTerminal.java │ └── util │ ├── ClassMap.java │ ├── FontUtil.java │ ├── Mcfw.java │ ├── McfwFilterType.java │ └── Utils.java └── resources ├── assets └── cmd-utils │ ├── icon.png │ └── lang │ └── en_us.json ├── cmd-utils.accesswidener ├── cmd-utils.mixins.json └── fabric.mod.json /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.toptal.com/developers/gitignore/api/java,gradle,intellij 2 | # Edit at https://www.toptal.com/developers/gitignore?templates=java,gradle,intellij 3 | 4 | ### Intellij ### 5 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider 6 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 7 | 8 | # User-specific stuff 9 | .idea/**/workspace.xml 10 | .idea/**/tasks.xml 11 | .idea/**/usage.statistics.xml 12 | .idea/**/dictionaries 13 | .idea/**/shelf 14 | 15 | # AWS User-specific 16 | .idea/**/aws.xml 17 | 18 | # Generated files 19 | .idea/**/contentModel.xml 20 | 21 | # Sensitive or high-churn files 22 | .idea/**/dataSources/ 23 | .idea/**/dataSources.ids 24 | .idea/**/dataSources.local.xml 25 | .idea/**/sqlDataSources.xml 26 | .idea/**/dynamic.xml 27 | .idea/**/uiDesigner.xml 28 | .idea/**/dbnavigator.xml 29 | 30 | # Gradle 31 | .idea/**/gradle.xml 32 | .idea/**/libraries 33 | 34 | # Gradle and Maven with auto-import 35 | # When using Gradle or Maven with auto-import, you should exclude module files, 36 | # since they will be recreated, and may cause churn. Uncomment if using 37 | # auto-import. 38 | # .idea/artifacts 39 | # .idea/compiler.xml 40 | # .idea/jarRepositories.xml 41 | # .idea/modules.xml 42 | # .idea/*.iml 43 | # .idea/modules 44 | # *.iml 45 | # *.ipr 46 | 47 | # CMake 48 | cmake-build-*/ 49 | 50 | # Mongo Explorer plugin 51 | .idea/**/mongoSettings.xml 52 | 53 | # File-based project format 54 | *.iws 55 | 56 | # IntelliJ 57 | out/ 58 | 59 | # mpeltonen/sbt-idea plugin 60 | .idea_modules/ 61 | 62 | # JIRA plugin 63 | atlassian-ide-plugin.xml 64 | 65 | # Cursive Clojure plugin 66 | .idea/replstate.xml 67 | 68 | # SonarLint plugin 69 | .idea/sonarlint/ 70 | 71 | # Crashlytics plugin (for Android Studio and IntelliJ) 72 | com_crashlytics_export_strings.xml 73 | crashlytics.properties 74 | crashlytics-build.properties 75 | fabric.properties 76 | 77 | # Editor-based Rest Client 78 | .idea/httpRequests 79 | 80 | # Android studio 3.1+ serialized cache file 81 | .idea/caches/build_file_checksums.ser 82 | 83 | ### Intellij Patch ### 84 | # Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 85 | 86 | # *.iml 87 | # modules.xml 88 | # .idea/misc.xml 89 | # *.ipr 90 | 91 | # Sonarlint plugin 92 | # https://plugins.jetbrains.com/plugin/7973-sonarlint 93 | .idea/**/sonarlint/ 94 | 95 | # SonarQube Plugin 96 | # https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin 97 | .idea/**/sonarIssues.xml 98 | 99 | # Markdown Navigator plugin 100 | # https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced 101 | .idea/**/markdown-navigator.xml 102 | .idea/**/markdown-navigator-enh.xml 103 | .idea/**/markdown-navigator/ 104 | 105 | # Cache file creation bug 106 | # See https://youtrack.jetbrains.com/issue/JBR-2257 107 | .idea/$CACHE_FILE$ 108 | 109 | # CodeStream plugin 110 | # https://plugins.jetbrains.com/plugin/12206-codestream 111 | .idea/codestream.xml 112 | 113 | # Azure Toolkit for IntelliJ plugin 114 | # https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij 115 | .idea/**/azureSettings.xml 116 | 117 | ### Java ### 118 | # Compiled class file 119 | *.class 120 | 121 | # Log file 122 | *.log 123 | 124 | # BlueJ files 125 | *.ctxt 126 | 127 | # Mobile Tools for Java (J2ME) 128 | .mtj.tmp/ 129 | 130 | # Package Files # 131 | *.jar 132 | *.war 133 | *.nar 134 | *.ear 135 | *.zip 136 | *.tar.gz 137 | *.rar 138 | 139 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 140 | hs_err_pid* 141 | replay_pid* 142 | 143 | ### Gradle ### 144 | .gradle 145 | **/build/ 146 | !src/**/build/ 147 | 148 | # Ignore Gradle GUI config 149 | gradle-app.setting 150 | 151 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) 152 | !gradle-wrapper.jar 153 | 154 | # Avoid ignore Gradle wrappper properties 155 | !gradle-wrapper.properties 156 | 157 | # Cache of project 158 | .gradletasknamecache 159 | 160 | # Eclipse Gradle plugin generated files 161 | # Eclipse Core 162 | .project 163 | # JDT-specific (Eclipse Java Development Tools) 164 | .classpath 165 | 166 | ### Gradle Patch ### 167 | # Java heap dump 168 | *.hprof 169 | 170 | # End of https://www.toptal.com/developers/gitignore/api/java,gradle,intellij 171 | 172 | 173 | # added 174 | 175 | bin/ 176 | .vscode/ 177 | run/ 178 | .idea/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Attribution-NonCommercial-ShareAlike 4.0 International 2 | 3 | ======================================================================= 4 | 5 | Creative Commons Corporation ("Creative Commons") is not a law firm and 6 | does not provide legal services or legal advice. Distribution of 7 | Creative Commons public licenses does not create a lawyer-client or 8 | other relationship. Creative Commons makes its licenses and related 9 | information available on an "as-is" basis. Creative Commons gives no 10 | warranties regarding its licenses, any material licensed under their 11 | terms and conditions, or any related information. Creative Commons 12 | disclaims all liability for damages resulting from their use to the 13 | fullest extent possible. 14 | 15 | Using Creative Commons Public Licenses 16 | 17 | Creative Commons public licenses provide a standard set of terms and 18 | conditions that creators and other rights holders may use to share 19 | original works of authorship and other material subject to copyright 20 | and certain other rights specified in the public license below. The 21 | following considerations are for informational purposes only, are not 22 | exhaustive, and do not form part of our licenses. 23 | 24 | Considerations for licensors: Our public licenses are 25 | intended for use by those authorized to give the public 26 | permission to use material in ways otherwise restricted by 27 | copyright and certain other rights. Our licenses are 28 | irrevocable. Licensors should read and understand the terms 29 | and conditions of the license they choose before applying it. 30 | Licensors should also secure all rights necessary before 31 | applying our licenses so that the public can reuse the 32 | material as expected. Licensors should clearly mark any 33 | material not subject to the license. This includes other CC- 34 | licensed material, or material used under an exception or 35 | limitation to copyright. More considerations for licensors: 36 | wiki.creativecommons.org/Considerations_for_licensors 37 | 38 | Considerations for the public: By using one of our public 39 | licenses, a licensor grants the public permission to use the 40 | licensed material under specified terms and conditions. If 41 | the licensor's permission is not necessary for any reason--for 42 | example, because of any applicable exception or limitation to 43 | copyright--then that use is not regulated by the license. Our 44 | licenses grant only permissions under copyright and certain 45 | other rights that a licensor has authority to grant. Use of 46 | the licensed material may still be restricted for other 47 | reasons, including because others have copyright or other 48 | rights in the material. A licensor may make special requests, 49 | such as asking that all changes be marked or described. 50 | Although not required by our licenses, you are encouraged to 51 | respect those requests where reasonable. More considerations 52 | for the public: 53 | wiki.creativecommons.org/Considerations_for_licensees 54 | 55 | ======================================================================= 56 | 57 | Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International 58 | Public License 59 | 60 | By exercising the Licensed Rights (defined below), You accept and agree 61 | to be bound by the terms and conditions of this Creative Commons 62 | Attribution-NonCommercial-ShareAlike 4.0 International Public License 63 | ("Public License"). To the extent this Public License may be 64 | interpreted as a contract, You are granted the Licensed Rights in 65 | consideration of Your acceptance of these terms and conditions, and the 66 | Licensor grants You such rights in consideration of benefits the 67 | Licensor receives from making the Licensed Material available under 68 | these terms and conditions. 69 | 70 | 71 | Section 1 -- Definitions. 72 | 73 | a. Adapted Material means material subject to Copyright and Similar 74 | Rights that is derived from or based upon the Licensed Material 75 | and in which the Licensed Material is translated, altered, 76 | arranged, transformed, or otherwise modified in a manner requiring 77 | permission under the Copyright and Similar Rights held by the 78 | Licensor. For purposes of this Public License, where the Licensed 79 | Material is a musical work, performance, or sound recording, 80 | Adapted Material is always produced where the Licensed Material is 81 | synched in timed relation with a moving image. 82 | 83 | b. Adapter's License means the license You apply to Your Copyright 84 | and Similar Rights in Your contributions to Adapted Material in 85 | accordance with the terms and conditions of this Public License. 86 | 87 | c. BY-NC-SA Compatible License means a license listed at 88 | creativecommons.org/compatiblelicenses, approved by Creative 89 | Commons as essentially the equivalent of this Public License. 90 | 91 | d. Copyright and Similar Rights means copyright and/or similar rights 92 | closely related to copyright including, without limitation, 93 | performance, broadcast, sound recording, and Sui Generis Database 94 | Rights, without regard to how the rights are labeled or 95 | categorized. For purposes of this Public License, the rights 96 | specified in Section 2(b)(1)-(2) are not Copyright and Similar 97 | Rights. 98 | 99 | e. Effective Technological Measures means those measures that, in the 100 | absence of proper authority, may not be circumvented under laws 101 | fulfilling obligations under Article 11 of the WIPO Copyright 102 | Treaty adopted on December 20, 1996, and/or similar international 103 | agreements. 104 | 105 | f. Exceptions and Limitations means fair use, fair dealing, and/or 106 | any other exception or limitation to Copyright and Similar Rights 107 | that applies to Your use of the Licensed Material. 108 | 109 | g. License Elements means the license attributes listed in the name 110 | of a Creative Commons Public License. The License Elements of this 111 | Public License are Attribution, NonCommercial, and ShareAlike. 112 | 113 | h. Licensed Material means the artistic or literary work, database, 114 | or other material to which the Licensor applied this Public 115 | License. 116 | 117 | i. Licensed Rights means the rights granted to You subject to the 118 | terms and conditions of this Public License, which are limited to 119 | all Copyright and Similar Rights that apply to Your use of the 120 | Licensed Material and that the Licensor has authority to license. 121 | 122 | j. Licensor means the individual(s) or entity(ies) granting rights 123 | under this Public License. 124 | 125 | k. NonCommercial means not primarily intended for or directed towards 126 | commercial advantage or monetary compensation. For purposes of 127 | this Public License, the exchange of the Licensed Material for 128 | other material subject to Copyright and Similar Rights by digital 129 | file-sharing or similar means is NonCommercial provided there is 130 | no payment of monetary compensation in connection with the 131 | exchange. 132 | 133 | l. Share means to provide material to the public by any means or 134 | process that requires permission under the Licensed Rights, such 135 | as reproduction, public display, public performance, distribution, 136 | dissemination, communication, or importation, and to make material 137 | available to the public including in ways that members of the 138 | public may access the material from a place and at a time 139 | individually chosen by them. 140 | 141 | m. Sui Generis Database Rights means rights other than copyright 142 | resulting from Directive 96/9/EC of the European Parliament and of 143 | the Council of 11 March 1996 on the legal protection of databases, 144 | as amended and/or succeeded, as well as other essentially 145 | equivalent rights anywhere in the world. 146 | 147 | n. You means the individual or entity exercising the Licensed Rights 148 | under this Public License. Your has a corresponding meaning. 149 | 150 | 151 | Section 2 -- Scope. 152 | 153 | a. License grant. 154 | 155 | 1. Subject to the terms and conditions of this Public License, 156 | the Licensor hereby grants You a worldwide, royalty-free, 157 | non-sublicensable, non-exclusive, irrevocable license to 158 | exercise the Licensed Rights in the Licensed Material to: 159 | 160 | a. reproduce and Share the Licensed Material, in whole or 161 | in part, for NonCommercial purposes only; and 162 | 163 | b. produce, reproduce, and Share Adapted Material for 164 | NonCommercial purposes only. 165 | 166 | 2. Exceptions and Limitations. For the avoidance of doubt, where 167 | Exceptions and Limitations apply to Your use, this Public 168 | License does not apply, and You do not need to comply with 169 | its terms and conditions. 170 | 171 | 3. Term. The term of this Public License is specified in Section 172 | 6(a). 173 | 174 | 4. Media and formats; technical modifications allowed. The 175 | Licensor authorizes You to exercise the Licensed Rights in 176 | all media and formats whether now known or hereafter created, 177 | and to make technical modifications necessary to do so. The 178 | Licensor waives and/or agrees not to assert any right or 179 | authority to forbid You from making technical modifications 180 | necessary to exercise the Licensed Rights, including 181 | technical modifications necessary to circumvent Effective 182 | Technological Measures. For purposes of this Public License, 183 | simply making modifications authorized by this Section 2(a) 184 | (4) never produces Adapted Material. 185 | 186 | 5. Downstream recipients. 187 | 188 | a. Offer from the Licensor -- Licensed Material. Every 189 | recipient of the Licensed Material automatically 190 | receives an offer from the Licensor to exercise the 191 | Licensed Rights under the terms and conditions of this 192 | Public License. 193 | 194 | b. Additional offer from the Licensor -- Adapted Material. 195 | Every recipient of Adapted Material from You 196 | automatically receives an offer from the Licensor to 197 | exercise the Licensed Rights in the Adapted Material 198 | under the conditions of the Adapter's License You apply. 199 | 200 | c. No downstream restrictions. You may not offer or impose 201 | any additional or different terms or conditions on, or 202 | apply any Effective Technological Measures to, the 203 | Licensed Material if doing so restricts exercise of the 204 | Licensed Rights by any recipient of the Licensed 205 | Material. 206 | 207 | 6. No endorsement. Nothing in this Public License constitutes or 208 | may be construed as permission to assert or imply that You 209 | are, or that Your use of the Licensed Material is, connected 210 | with, or sponsored, endorsed, or granted official status by, 211 | the Licensor or others designated to receive attribution as 212 | provided in Section 3(a)(1)(A)(i). 213 | 214 | b. Other rights. 215 | 216 | 1. Moral rights, such as the right of integrity, are not 217 | licensed under this Public License, nor are publicity, 218 | privacy, and/or other similar personality rights; however, to 219 | the extent possible, the Licensor waives and/or agrees not to 220 | assert any such rights held by the Licensor to the limited 221 | extent necessary to allow You to exercise the Licensed 222 | Rights, but not otherwise. 223 | 224 | 2. Patent and trademark rights are not licensed under this 225 | Public License. 226 | 227 | 3. To the extent possible, the Licensor waives any right to 228 | collect royalties from You for the exercise of the Licensed 229 | Rights, whether directly or through a collecting society 230 | under any voluntary or waivable statutory or compulsory 231 | licensing scheme. In all other cases the Licensor expressly 232 | reserves any right to collect such royalties, including when 233 | the Licensed Material is used other than for NonCommercial 234 | purposes. 235 | 236 | 237 | Section 3 -- License Conditions. 238 | 239 | Your exercise of the Licensed Rights is expressly made subject to the 240 | following conditions. 241 | 242 | a. Attribution. 243 | 244 | 1. If You Share the Licensed Material (including in modified 245 | form), You must: 246 | 247 | a. retain the following if it is supplied by the Licensor 248 | with the Licensed Material: 249 | 250 | i. identification of the creator(s) of the Licensed 251 | Material and any others designated to receive 252 | attribution, in any reasonable manner requested by 253 | the Licensor (including by pseudonym if 254 | designated); 255 | 256 | ii. a copyright notice; 257 | 258 | iii. a notice that refers to this Public License; 259 | 260 | iv. a notice that refers to the disclaimer of 261 | warranties; 262 | 263 | v. a URI or hyperlink to the Licensed Material to the 264 | extent reasonably practicable; 265 | 266 | b. indicate if You modified the Licensed Material and 267 | retain an indication of any previous modifications; and 268 | 269 | c. indicate the Licensed Material is licensed under this 270 | Public License, and include the text of, or the URI or 271 | hyperlink to, this Public License. 272 | 273 | 2. You may satisfy the conditions in Section 3(a)(1) in any 274 | reasonable manner based on the medium, means, and context in 275 | which You Share the Licensed Material. For example, it may be 276 | reasonable to satisfy the conditions by providing a URI or 277 | hyperlink to a resource that includes the required 278 | information. 279 | 3. If requested by the Licensor, You must remove any of the 280 | information required by Section 3(a)(1)(A) to the extent 281 | reasonably practicable. 282 | 283 | b. ShareAlike. 284 | 285 | In addition to the conditions in Section 3(a), if You Share 286 | Adapted Material You produce, the following conditions also apply. 287 | 288 | 1. The Adapter's License You apply must be a Creative Commons 289 | license with the same License Elements, this version or 290 | later, or a BY-NC-SA Compatible License. 291 | 292 | 2. You must include the text of, or the URI or hyperlink to, the 293 | Adapter's License You apply. You may satisfy this condition 294 | in any reasonable manner based on the medium, means, and 295 | context in which You Share Adapted Material. 296 | 297 | 3. You may not offer or impose any additional or different terms 298 | or conditions on, or apply any Effective Technological 299 | Measures to, Adapted Material that restrict exercise of the 300 | rights granted under the Adapter's License You apply. 301 | 302 | 303 | Section 4 -- Sui Generis Database Rights. 304 | 305 | Where the Licensed Rights include Sui Generis Database Rights that 306 | apply to Your use of the Licensed Material: 307 | 308 | a. for the avoidance of doubt, Section 2(a)(1) grants You the right 309 | to extract, reuse, reproduce, and Share all or a substantial 310 | portion of the contents of the database for NonCommercial purposes 311 | only; 312 | 313 | b. if You include all or a substantial portion of the database 314 | contents in a database in which You have Sui Generis Database 315 | Rights, then the database in which You have Sui Generis Database 316 | Rights (but not its individual contents) is Adapted Material, 317 | including for purposes of Section 3(b); and 318 | 319 | c. You must comply with the conditions in Section 3(a) if You Share 320 | all or a substantial portion of the contents of the database. 321 | 322 | For the avoidance of doubt, this Section 4 supplements and does not 323 | replace Your obligations under this Public License where the Licensed 324 | Rights include other Copyright and Similar Rights. 325 | 326 | 327 | Section 5 -- Disclaimer of Warranties and Limitation of Liability. 328 | 329 | a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE 330 | EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS 331 | AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF 332 | ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, 333 | IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, 334 | WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR 335 | PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, 336 | ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT 337 | KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT 338 | ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. 339 | 340 | b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE 341 | TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, 342 | NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, 343 | INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, 344 | COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR 345 | USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN 346 | ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR 347 | DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR 348 | IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. 349 | 350 | c. The disclaimer of warranties and limitation of liability provided 351 | above shall be interpreted in a manner that, to the extent 352 | possible, most closely approximates an absolute disclaimer and 353 | waiver of all liability. 354 | 355 | 356 | Section 6 -- Term and Termination. 357 | 358 | a. This Public License applies for the term of the Copyright and 359 | Similar Rights licensed here. However, if You fail to comply with 360 | this Public License, then Your rights under this Public License 361 | terminate automatically. 362 | 363 | b. Where Your right to use the Licensed Material has terminated under 364 | Section 6(a), it reinstates: 365 | 366 | 1. automatically as of the date the violation is cured, provided 367 | it is cured within 30 days of Your discovery of the 368 | violation; or 369 | 370 | 2. upon express reinstatement by the Licensor. 371 | 372 | For the avoidance of doubt, this Section 6(b) does not affect any 373 | right the Licensor may have to seek remedies for Your violations 374 | of this Public License. 375 | 376 | c. For the avoidance of doubt, the Licensor may also offer the 377 | Licensed Material under separate terms or conditions or stop 378 | distributing the Licensed Material at any time; however, doing so 379 | will not terminate this Public License. 380 | 381 | d. Sections 1, 5, 6, 7, and 8 survive termination of this Public 382 | License. 383 | 384 | 385 | Section 7 -- Other Terms and Conditions. 386 | 387 | a. The Licensor shall not be bound by any additional or different 388 | terms or conditions communicated by You unless expressly agreed. 389 | 390 | b. Any arrangements, understandings, or agreements regarding the 391 | Licensed Material not stated herein are separate from and 392 | independent of the terms and conditions of this Public License. 393 | 394 | 395 | Section 8 -- Interpretation. 396 | 397 | a. For the avoidance of doubt, this Public License does not, and 398 | shall not be interpreted to, reduce, limit, restrict, or impose 399 | conditions on any use of the Licensed Material that could lawfully 400 | be made without permission under this Public License. 401 | 402 | b. To the extent possible, if any provision of this Public License is 403 | deemed unenforceable, it shall be automatically reformed to the 404 | minimum extent necessary to make it enforceable. If the provision 405 | cannot be reformed, it shall be severed from this Public License 406 | without affecting the enforceability of the remaining terms and 407 | conditions. 408 | 409 | c. No term or condition of this Public License will be waived and no 410 | failure to comply consented to unless expressly agreed to by the 411 | Licensor. 412 | 413 | d. Nothing in this Public License constitutes or may be interpreted 414 | as a limitation upon, or waiver of, any privileges and immunities 415 | that apply to the Licensor or You, including from the legal 416 | processes of any jurisdiction or authority. 417 | 418 | ======================================================================= 419 | 420 | Creative Commons is not a party to its public 421 | licenses. Notwithstanding, Creative Commons may elect to apply one of 422 | its public licenses to material it publishes and in those instances 423 | will be considered the “Licensor.” The text of the Creative Commons 424 | public licenses is dedicated to the public domain under the CC0 Public 425 | Domain Dedication. Except for the limited purpose of indicating that 426 | material is shared under a Creative Commons public license or as 427 | otherwise permitted by the Creative Commons policies published at 428 | creativecommons.org/policies, Creative Commons does not authorize the 429 | use of the trademark "Creative Commons" or any other trademark or logo 430 | of Creative Commons without its prior written consent including, 431 | without limitation, in connection with any unauthorized modifications 432 | to any of its public licenses or any other arrangements, 433 | understandings, or agreements concerning use of licensed material. For 434 | the avoidance of doubt, this paragraph does not form part of the 435 | public licenses. 436 | 437 | Creative Commons may be contacted at creativecommons.org. 438 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CMD Utils 2 | 3 | CMD-Utils is a FabricMC Minecraft modification used for debugging mods, plugins, and servers 4 | using a command line with many features useful for glitch hunting. 5 | 6 | --- 7 | 8 | ## About 9 | 10 | CMD-Utils was created due to issues with maintaining UI-Utils, CMD-Utils is able to do 11 | everything that UI-Utils can and more. CMD-Utils as well as UI-Utils will be updated 12 | to the latest version of Minecraft as quickly as possible. This mod is not intended to 13 | kill UI-Utils. 14 | 15 | --- 16 | 17 | ## Contact 18 | 19 | Discord Server:\ 20 | https://discord.gg/NaKb65CEZn 21 | 22 | Coderx Gamer (owner):\ 23 | Discord: public_static_void_main_args\ 24 | Email: [coderx@mailfence.com](mailto:coderx@mailfence.com) 25 | 26 | MrBreakNFix (developer):\ 27 | Discord: mrbreaknfix 28 | 29 | --- 30 | 31 | ## Building 32 | 33 | CMD-Utils does not distribute any binaries of itself, as it is harder to maintain 34 | and less safe. You must build CMD-Utils from source to use it. 35 | 36 | To build CMD-Utils on Linux, run these commands in a terminal: 37 | 38 | ```shell 39 | git clone https://github.com/Coderx-Gamer/cmd-utils.git 40 | cd ./cmd-utils/ 41 | chmod +x ./gradlew 42 | ./gradlew build 43 | ``` 44 | 45 | To build on Windows, click the green "Code" button and click "Download ZIP," 46 | extract it, go into that folder in File Explorer, then do SHIFT+Right Click 47 | and click "Open PowerShell window here," in that window, type `./gradlew build`. 48 | 49 | Now that you built CMD-Utils, your jar file should be located at `./build/libs/cmd-utils-.jar` 50 | 51 | --- 52 | 53 | ## Documentation 54 | 55 | ### Using the terminal 56 | 57 | To get started with CMD-Utils, open a terminal by pressing the keybinding in the controls 58 | menu (Y by default) and if you are in a GUI, do CTRL+Y. When you close this GUI it will 59 | go back to whatever GUI you had open before (or none if you opened it without a GUI open.) 60 | 61 | You can enter a command into the terminal by typing it and pressing enter, and scroll through 62 | your command history with the up and down arrow keys. 63 | 64 | If you want to send multiple commands at once, press CTRL+Enter while sending the command, 65 | and when you are done, send the last command with only the enter key. 66 | 67 | If you prefer an external terminal window, you can run the 'swing' command to open a new 68 | one using Java Swing. 69 | 70 | ### Commands 71 | 72 | There are many commands in CMD-Utils, which will be listed here, there will be more commands 73 | added in the future. 74 | 75 | [help](./docs/help.md) - Show the help menu.\ 76 | [cmdutils](./docs/cmdutils.md) - Show CMD-Utils information\ 77 | [clear](./docs/clear.md) - Clear the log.\ 78 | [swing](./docs/swing.md) - Open the Java Swing terminal.\ 79 | [loop](./docs/loop.md) - Loop a command any amount of times.\ 80 | [leave](./docs/leave.md) - Leave a server or single player world.\ 81 | [menuinfo](./docs/menuinfo.md) - Show GUI information.\ 82 | [savegui](./docs/savegui.md) - Save your current GUI, so it can be restored later.\ 83 | [restoregui](./docs/restoregui.md) - Restore your saved GUI.\ 84 | [close](./docs/close.md) - Close your GUI without sending a packet.\ 85 | [desync](./docs/desync.md) - Send a CloseHandledScreen packet without closing your GUI (client-side.)\ 86 | [chat](./docs/chat.md) - Send a chat message or command.\ 87 | [rpack](./docs/rpack.md) - Resource pack bypass tool.\ 88 | [wake](./docs/wake.md) - Wake up from a bed (client-side.)\ 89 | [drop](./docs/drop.md) - Drop your selected item.\ 90 | [trade](./docs/trade.md) - Select a villager trade by ID.\ 91 | [button](./docs/button.md) - Send a ButtonClick packet.\ 92 | [click](./docs/click.md) - Send a ClickSlot packet.\ 93 | [mcfw](./docs/mcfw.md) - Minecraft Firewall packet filter.\ 94 | [session](./docs/session.md) - Session ID getter/setter. 95 | 96 | --- 97 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'fabric-loom' version '1.4-SNAPSHOT' 3 | id 'maven-publish' 4 | } 5 | 6 | version = project.mod_version 7 | group = project.maven_group 8 | 9 | base { 10 | archivesName = project.archives_base_name 11 | } 12 | 13 | repositories { 14 | // Add repositories to retrieve artifacts from in here. 15 | // You should only use this when depending on other mods because 16 | // Loom adds the essential maven repositories to download Minecraft and libraries from automatically. 17 | // See https://docs.gradle.org/current/userguide/declaring_repositories.html 18 | // for more information about repositories. 19 | } 20 | 21 | dependencies { 22 | // To change the versions see the gradle.properties file 23 | minecraft "com.mojang:minecraft:${project.minecraft_version}" 24 | mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" 25 | modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" 26 | 27 | // Fabric API. This is technically optional, but you probably want it anyway. 28 | modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" 29 | 30 | // Uncomment the following line to enable the deprecated Fabric API modules. 31 | // These are included in the Fabric API production distribution and allow you to update your mod to the latest modules at a later more convenient time. 32 | 33 | // modImplementation "net.fabricmc.fabric-api:fabric-api-deprecated:${project.fabric_version}" 34 | } 35 | 36 | loom { 37 | accessWidenerPath = file("src/main/resources/cmd-utils.accesswidener") 38 | } 39 | 40 | processResources { 41 | inputs.property "version", project.version 42 | 43 | filesMatching("fabric.mod.json") { 44 | expand "version": project.version 45 | } 46 | } 47 | 48 | tasks.withType(JavaCompile).configureEach { 49 | it.options.release = 17 50 | } 51 | 52 | java { 53 | // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task 54 | // if it is present. 55 | // If you remove this line, sources will not be generated. 56 | withSourcesJar() 57 | 58 | sourceCompatibility = JavaVersion.VERSION_17 59 | targetCompatibility = JavaVersion.VERSION_17 60 | } 61 | 62 | jar { 63 | from("LICENSE") { 64 | rename { "${it}_${project.base.archivesName.get()}"} 65 | } 66 | } 67 | 68 | // configure the maven publication 69 | publishing { 70 | publications { 71 | mavenJava(MavenPublication) { 72 | from components.java 73 | } 74 | } 75 | 76 | // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. 77 | repositories { 78 | // Add repositories to publish to here. 79 | // Notice: This block does NOT have the same function as the block in the top level. 80 | // The repositories here will be used for publishing your artifact, not for 81 | // retrieving dependencies. 82 | } 83 | } -------------------------------------------------------------------------------- /classmap-generator/Makefile: -------------------------------------------------------------------------------- 1 | all: ./src/main.cpp 2 | g++ -Wall ./src/main.cpp -o ./bin/cmgen -lcurl -lcurlpp 3 | clean: 4 | rm ./bin/cmgen 5 | -------------------------------------------------------------------------------- /classmap-generator/README: -------------------------------------------------------------------------------- 1 | Class Map Generator 2 | =================== 3 | 4 | Class Map Generator is a basic tool for generating Java maps from compiled class names to 5 | short packet names, this is used in CMD-Utils for the packet filter (mcfw.) 6 | 7 | 8 | Building 9 | ======== 10 | 11 | To build Class Map Generator, run 'make' in this directory and it will build a binary at 12 | './bin/cmgen'. To get rid of it, run 'make clean'. 13 | 14 | You need to have libcurl and libcurlpp installed to build this. 15 | 16 | 17 | Usage 18 | ===== 19 | 20 | I would not recommend using this tool as the code is a bit messy and may break if the 21 | Javadoc website (https://maven.fabricmc.net/) updates. 22 | 23 | But if you still want to use it, first, build it, then, run 24 | './bin/cmgen ', you can find the latest yarn version on this site: 25 | https://fabricmc.net/develop/ if you scroll down a bit. Running this program may take 26 | up to a few minutes depending on your network speed. The program will generate Java 27 | code for a 'ClassMap' class which can be pasted into 'org.cmdutils.util.ClassMap' 28 | in CMD-Utils. 29 | -------------------------------------------------------------------------------- /classmap-generator/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using std::cout; 10 | using std::endl; 11 | using std::map; 12 | using std::string; 13 | using std::stringstream; 14 | 15 | using namespace curlpp; 16 | using namespace curlpp::options; 17 | 18 | void issue(string problem) 19 | { 20 | cout << "Error: " << problem << '\n'; 21 | exit(1); 22 | } 23 | 24 | string replace_all(string subject, const string &search, const string &replace) 25 | { 26 | size_t pos = 0; 27 | while ((pos = subject.find(search, pos)) != string::npos) 28 | { 29 | subject.replace(pos, search.length(), replace); 30 | pos += replace.length(); 31 | } 32 | return subject; 33 | } 34 | 35 | string http_get(const string &url) { 36 | stringstream response_stream; 37 | 38 | try 39 | { 40 | Cleanup cleanup; 41 | Easy request; 42 | 43 | request.setOpt(new Url(url)); 44 | request.setOpt(new WriteStream(&response_stream)); 45 | 46 | request.perform(); 47 | } 48 | catch (RuntimeError &e) 49 | { 50 | cout << "curlpp runtime error: " << e.what() << endl; 51 | exit(1); 52 | } 53 | catch (LogicError &e) 54 | { 55 | cout << "curlpp logic error: " << e.what() << endl; 56 | exit(1); 57 | } 58 | 59 | return response_stream.str(); 60 | } 61 | 62 | string slice_str(const string &str, int start, int end) 63 | { 64 | end += start; 65 | string new_str; 66 | int i; 67 | for (i = 0; i < (int) str.length(); ++i) 68 | { 69 | if (!(i > start && i < end)) 70 | new_str += str[i]; 71 | } 72 | return new_str; 73 | } 74 | 75 | string replace_char(string str, char c, char nc) 76 | { 77 | size_t i; 78 | for (i = 0; i < str.length(); ++i) 79 | { 80 | if (str[i] == c) 81 | { 82 | str[i] = nc; 83 | break; 84 | } 85 | } 86 | return str; 87 | } 88 | 89 | string format_html_line(const string &line) 90 | { 91 | return line.substr(0, line.find_first_of('<')); 92 | } 93 | 94 | string trim_packet(const string &packet) 95 | { 96 | string modified = replace_char(packet, '.', '$'); 97 | return slice_str(modified, modified.rfind("C2SPacket") - 1, 10); 98 | } 99 | 100 | string intermediate_name(const string &packet, const string &package, const string &version) 101 | { 102 | string res = http_get("https://maven.fabricmc.net/docs/" + version + "/net/minecraft/network/packet/c2s/" + package + "/" + packet + ".html"); 103 | size_t location = res.rfind("intermediary\nnet/minecraft/"); 104 | if (location == string::npos) 105 | issue("Failed To Scrape Intermediate Class Name (Packet Name: " + packet + ")."); 106 | string name = res.substr(location + 69, 22); 107 | return name.substr(0, name.find_first_of('<')); 108 | } 109 | 110 | void get_packets(map &packet_map, const string &package, const string &version) 111 | { 112 | cout << "Fetching classes in net.minecraft.network.packet.c2s." << package << ".\n"; 113 | string res = replace_all(http_get("https://maven.fabricmc.net/docs/" + version + "/net/minecraft/network/packet/c2s/" + package + "/package-summary.html"), "\"class in net.minecraft.network.packet.c2s." + package + "\">", "\n"); 114 | string line; 115 | size_t i; 116 | for (i = 0; i < res.length(); ++i) 117 | { 118 | if (res[i] == '\n') 119 | { 120 | if (line[0] != '<' && line[0] != 'l' && line[0] != ' ') 121 | { 122 | line = format_html_line(line); 123 | if (line.rfind("C2SPacket") != string::npos && line != "PlayerMoveC2SPacket") 124 | packet_map[intermediate_name(line, package, version)] = trim_packet(line); 125 | } 126 | line = {}; 127 | continue; 128 | } 129 | 130 | line += res[i]; 131 | } 132 | } 133 | 134 | map get_all_packets(const string &version) 135 | { 136 | map packet_map; 137 | get_packets(packet_map, "play", version); 138 | get_packets(packet_map, "common", version); 139 | get_packets(packet_map, "config", version); 140 | get_packets(packet_map, "query", version); 141 | get_packets(packet_map, "login", version); 142 | get_packets(packet_map, "handshake", version); 143 | return packet_map; 144 | } 145 | 146 | int main(int argc, char **argv) 147 | { 148 | if (argc != 2) 149 | issue("Invalid Arguments, usage: 'cmgen '."); 150 | 151 | string version = string(argv[1]); 152 | 153 | cout << "This may take a few minutes ...\n"; 154 | 155 | map packets = get_all_packets(version); 156 | 157 | cout << "\nJava Code:\n\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class ClassMap {\n public static final Map PACKET_MAP = new HashMap<>();\n\n static {\n"; 158 | 159 | for (const auto &[key, value] : packets) 160 | { 161 | cout << " PACKET_MAP.put(\"" << key << "\", \"" << value << "\");\n"; 162 | 163 | } 164 | cout << " }\n}\n\nDone.\n"; 165 | 166 | return 0; 167 | } 168 | -------------------------------------------------------------------------------- /docs/button.md: -------------------------------------------------------------------------------- 1 | # Button 2 | 3 | Send a ButtonClick packet. 4 | 5 | Usage:\ 6 | - button <sync id (or "current")> <button id> 7 | 8 | --- -------------------------------------------------------------------------------- /docs/chat.md: -------------------------------------------------------------------------------- 1 | # Chat 2 | 3 | Send a chat message or command. 4 | 5 | Usage:\ 6 | - chat "<message>"\ 7 | - chat "<command>" cmd 8 | 9 | --- -------------------------------------------------------------------------------- /docs/clear.md: -------------------------------------------------------------------------------- 1 | # Clear 2 | 3 | Clear the log (Swing Or In Game.) 4 | 5 | Usage:\ 6 | - clear 7 | 8 | --- -------------------------------------------------------------------------------- /docs/click.md: -------------------------------------------------------------------------------- 1 | # Click 2 | 3 | Send a ClickSlot packet. 4 | 5 | Usage:\ 6 | - click <sync id (or "current")> <revision (or "current")> <slot> <button> <action: pickup, quick-move, swap, clone, throw, quick-craft, pickup-all> 7 | 8 | --- -------------------------------------------------------------------------------- /docs/close.md: -------------------------------------------------------------------------------- 1 | # Close 2 | 3 | Close your GUI without sending a packet. 4 | 5 | Usage:\ 6 | - close 7 | 8 | --- -------------------------------------------------------------------------------- /docs/cmdutils.md: -------------------------------------------------------------------------------- 1 | # Cmdutils 2 | 3 | Show CMD-Utils information. 4 | 5 | Usage:\ 6 | - cmdutils 7 | 8 | --- -------------------------------------------------------------------------------- /docs/desync.md: -------------------------------------------------------------------------------- 1 | # Desync 2 | 3 | Send a CloseHandledScreen packet without closing your GUI (client-side.) 4 | 5 | Usage:\ 6 | - desync 7 | 8 | --- -------------------------------------------------------------------------------- /docs/drop.md: -------------------------------------------------------------------------------- 1 | # Drop 2 | 3 | Drop your selected item. 4 | 5 | Usage:\ 6 | - drop\ 7 | - drop all 8 | 9 | --- 10 | -------------------------------------------------------------------------------- /docs/help.md: -------------------------------------------------------------------------------- 1 | # Help 2 | 3 | Show a list of commands with descriptions or description of one command. 4 | 5 | Usage:\ 6 | - help\ 7 | - help <command> 8 | 9 | --- -------------------------------------------------------------------------------- /docs/leave.md: -------------------------------------------------------------------------------- 1 | # Leave 2 | 3 | Leave a server or single player world. 4 | 5 | Usage:\ 6 | - leave 7 | 8 | --- -------------------------------------------------------------------------------- /docs/loop.md: -------------------------------------------------------------------------------- 1 | # Loop 2 | 3 | Loop a command any amount of times. 4 | 5 | Usage:\ 6 | - loop <times to loop> <command name> <argument 1> <argument 2> ... 7 | 8 | --- -------------------------------------------------------------------------------- /docs/mcfw.md: -------------------------------------------------------------------------------- 1 | # MCFW 2 | 3 | Minecraft Firewall packet filter. 4 | 5 | Usage:\ 6 | - mcfw status (show ON/OFF)\ 7 | - mcfw enable (enable MCFW)\ 8 | - mcfw disable (disable MCFW)\ 9 | - mcfw quiet-disable (disable without sending delayed packets)\ 10 | - mcfw list (list packet filter)\ 11 | - mcfw delayed (show delayed packets count)\ 12 | - mcfw clear (clear packet filter)\ 13 | - mcfw clear-delayed (clear delayed packets queue)\ 14 | - mcfw block <packet name> (block outgoing packet)\ 15 | - mcfw delay <packet name> (delay (until disable) outgoing packet)\ 16 | - mcfw remove <packet name> (remove from packet filter) 17 | 18 | Packet Names:\ 19 | TeleportConfirm\ 20 | QueryBlockNbt\ 21 | ChatMessage\ 22 | ClientStatus\ 23 | ClientOptions\ 24 | RequestCommandCompletions\ 25 | ButtonClick\ 26 | ClickSlot\ 27 | CloseHandledScreen\ 28 | CustomPayload\ 29 | BookUpdate\ 30 | QueryEntityNbt\ 31 | PlayerInteractEntity\ 32 | PlayerInteractEntity$InteractHandler\ 33 | PlayerInteractEntity$InteractAtHandler\ 34 | KeepAlive\ 35 | PlayerMove$PositionAndOnGround\ 36 | PlayerMove$Full\ 37 | PlayerMove$LookAndOnGround\ 38 | PlayerMove$OnGroundOnly\ 39 | VehicleMove\ 40 | BoatPaddleState\ 41 | PickFromInventory\ 42 | CraftRequest\ 43 | UpdatePlayerAbilities\ 44 | PlayerAction\ 45 | ClientCommand\ 46 | PlayerInput\ 47 | RecipeBookData\ 48 | RenameItem\ 49 | ResourcePackStatus\ 50 | AdvancementTab\ 51 | SelectMerchantTrade\ 52 | UpdateBeacon\ 53 | UpdateSelectedSlot\ 54 | UpdateCommandBlock\ 55 | UpdateCommandBlockMinecart\ 56 | CreativeInventoryAction\ 57 | UpdateStructureBlock\ 58 | UpdateSign\ 59 | HandSwing\ 60 | SpectatorTeleport\ 61 | PlayerInteractBlock\ 62 | PlayerInteractItem\ 63 | Handshake\ 64 | LoginQueryResponse\ 65 | LoginHello\ 66 | LoginKey\ 67 | QueryPing\ 68 | QueryRequest\ 69 | UpdateJigsaw\ 70 | UpdateDifficulty\ 71 | UpdateDifficultyLock\ 72 | JigsawGenerating\ 73 | RecipeCategoryOptions\ 74 | CommonPong\ 75 | CommandExecution\ 76 | MessageAcknowledgment\ 77 | PlayerSession\ 78 | AcknowledgeChunks\ 79 | AcknowledgeReconfiguration\ 80 | EnterConfiguration\ 81 | Ready 82 | 83 | --- -------------------------------------------------------------------------------- /docs/menuinfo.md: -------------------------------------------------------------------------------- 1 | # Menuinfo 2 | 3 | Show GUI information. 4 | 5 | Usage:\ 6 | - menuinfo 7 | 8 | --- -------------------------------------------------------------------------------- /docs/restoregui.md: -------------------------------------------------------------------------------- 1 | # Restoregui 2 | 3 | Restore your saved GUI created using [savegui](savegui.md). 4 | 5 | Usage:\ 6 | - restoregui 7 | 8 | --- -------------------------------------------------------------------------------- /docs/rpack.md: -------------------------------------------------------------------------------- 1 | # Rpack 2 | 3 | Resource pack bypass tool. 4 | 5 | Usage:\ 6 | - rpack <accepted, declined, loaded, failed> 7 | 8 | --- -------------------------------------------------------------------------------- /docs/savegui.md: -------------------------------------------------------------------------------- 1 | # Savegui 2 | 3 | Save your current GUI, so it can be restored later. 4 | 5 | It can later be restored using [restoregui](restoregui.md). 6 | 7 | Usage:\ 8 | - savegui 9 | 10 | --- -------------------------------------------------------------------------------- /docs/session.md: -------------------------------------------------------------------------------- 1 | # Session 2 | 3 | Session ID getter/setter. 4 | 5 | WARNING! If someone asks you to run 'session get' and see the output, they are trying to steal your account. 6 | Do not share it with anyone you don't trust. 7 | 8 | Usage:\ 9 | - session get\ 10 | - session set <field: username, uuid, token, or type (type can be: msa, mojang, or legacy)> <value> 11 | 12 | --- -------------------------------------------------------------------------------- /docs/swing.md: -------------------------------------------------------------------------------- 1 | # Swing 2 | 3 | Open the Java Swing terminal. 4 | 5 | There may be issues with this on OSX. 6 | 7 | Usage:\ 8 | - swing 9 | 10 | --- -------------------------------------------------------------------------------- /docs/trade.md: -------------------------------------------------------------------------------- 1 | # Trade 2 | 3 | Select a villager trade by ID. 4 | 5 | Usage:\ 6 | - trade <trade id> 7 | 8 | --- -------------------------------------------------------------------------------- /docs/wake.md: -------------------------------------------------------------------------------- 1 | # Wake 2 | 3 | Wake up from a bed (client-side.) 4 | 5 | Usage:\ 6 | - wake 7 | 8 | --- -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Done to increase the memory available to gradle. 2 | org.gradle.jvmargs=-Xmx1G 3 | org.gradle.parallel=true 4 | 5 | # Fabric Properties 6 | # check these on https://fabricmc.net/develop 7 | minecraft_version=1.20.4 8 | yarn_mappings=1.20.4+build.1 9 | loader_version=0.15.1 10 | 11 | # Mod Properties 12 | mod_version=1.0.2 13 | maven_group=org.cmdutils 14 | archives_base_name=cmd-utils 15 | 16 | # Dependencies 17 | fabric_version=0.91.2+1.20.4 18 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Coderx-Gamer/cmd-utils/4d143c466034094e0d48caf83dcecfc19cdaa0ac/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # Copyright © 2015-2021 the original authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | # 21 | # Gradle start up script for POSIX generated by Gradle. 22 | # 23 | # Important for running: 24 | # 25 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is 26 | # noncompliant, but you have some other compliant shell such as ksh or 27 | # bash, then to run this script, type that shell name before the whole 28 | # command line, like: 29 | # 30 | # ksh Gradle 31 | # 32 | # Busybox and similar reduced shells will NOT work, because this script 33 | # requires all of these POSIX shell features: 34 | # * functions; 35 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}», 36 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»; 37 | # * compound commands having a testable exit status, especially «case»; 38 | # * various built-in commands including «command», «set», and «ulimit». 39 | # 40 | # Important for patching: 41 | # 42 | # (2) This script targets any POSIX shell, so it avoids extensions provided 43 | # by Bash, Ksh, etc; in particular arrays are avoided. 44 | # 45 | # The "traditional" practice of packing multiple parameters into a 46 | # space-separated string is a well documented source of bugs and security 47 | # problems, so this is (mostly) avoided, by progressively accumulating 48 | # options in "$@", and eventually passing that to Java. 49 | # 50 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, 51 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; 52 | # see the in-line comments for details. 53 | # 54 | # There are tweaks for specific operating systems such as AIX, CygWin, 55 | # Darwin, MinGW, and NonStop. 56 | # 57 | # (3) This script is generated from the Groovy template 58 | # https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt 59 | # within the Gradle project. 60 | # 61 | # You can find Gradle at https://github.com/gradle/gradle/. 62 | # 63 | ############################################################################## 64 | 65 | # Attempt to set APP_HOME 66 | 67 | # Resolve links: $0 may be a link 68 | app_path=$0 69 | 70 | # Need this for daisy-chained symlinks. 71 | while 72 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path 73 | [ -h "$app_path" ] 74 | do 75 | ls=$( ls -ld "$app_path" ) 76 | link=${ls#*' -> '} 77 | case $link in #( 78 | /*) app_path=$link ;; #( 79 | *) app_path=$APP_HOME$link ;; 80 | esac 81 | done 82 | 83 | # This is normally unused 84 | # shellcheck disable=SC2034 85 | APP_BASE_NAME=${0##*/} 86 | # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) 87 | APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit 88 | 89 | # Use the maximum available, or set MAX_FD != -1 to use that value. 90 | MAX_FD=maximum 91 | 92 | warn () { 93 | echo "$*" 94 | } >&2 95 | 96 | die () { 97 | echo 98 | echo "$*" 99 | echo 100 | exit 1 101 | } >&2 102 | 103 | # OS specific support (must be 'true' or 'false'). 104 | cygwin=false 105 | msys=false 106 | darwin=false 107 | nonstop=false 108 | case "$( uname )" in #( 109 | CYGWIN* ) cygwin=true ;; #( 110 | Darwin* ) darwin=true ;; #( 111 | MSYS* | MINGW* ) msys=true ;; #( 112 | NONSTOP* ) nonstop=true ;; 113 | esac 114 | 115 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 116 | 117 | 118 | # Determine the Java command to use to start the JVM. 119 | if [ -n "$JAVA_HOME" ] ; then 120 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 121 | # IBM's JDK on AIX uses strange locations for the executables 122 | JAVACMD=$JAVA_HOME/jre/sh/java 123 | else 124 | JAVACMD=$JAVA_HOME/bin/java 125 | fi 126 | if [ ! -x "$JAVACMD" ] ; then 127 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 128 | 129 | Please set the JAVA_HOME variable in your environment to match the 130 | location of your Java installation." 131 | fi 132 | else 133 | JAVACMD=java 134 | if ! command -v java >/dev/null 2>&1 135 | then 136 | die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 137 | 138 | Please set the JAVA_HOME variable in your environment to match the 139 | location of your Java installation." 140 | fi 141 | fi 142 | 143 | # Increase the maximum file descriptors if we can. 144 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then 145 | case $MAX_FD in #( 146 | max*) 147 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. 148 | # shellcheck disable=SC3045 149 | MAX_FD=$( ulimit -H -n ) || 150 | warn "Could not query maximum file descriptor limit" 151 | esac 152 | case $MAX_FD in #( 153 | '' | soft) :;; #( 154 | *) 155 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. 156 | # shellcheck disable=SC3045 157 | ulimit -n "$MAX_FD" || 158 | warn "Could not set maximum file descriptor limit to $MAX_FD" 159 | esac 160 | fi 161 | 162 | # Collect all arguments for the java command, stacking in reverse order: 163 | # * args from the command line 164 | # * the main class name 165 | # * -classpath 166 | # * -D...appname settings 167 | # * --module-path (only if needed) 168 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. 169 | 170 | # For Cygwin or MSYS, switch paths to Windows format before running java 171 | if "$cygwin" || "$msys" ; then 172 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) 173 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) 174 | 175 | JAVACMD=$( cygpath --unix "$JAVACMD" ) 176 | 177 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 178 | for arg do 179 | if 180 | case $arg in #( 181 | -*) false ;; # don't mess with options #( 182 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath 183 | [ -e "$t" ] ;; #( 184 | *) false ;; 185 | esac 186 | then 187 | arg=$( cygpath --path --ignore --mixed "$arg" ) 188 | fi 189 | # Roll the args list around exactly as many times as the number of 190 | # args, so each arg winds up back in the position where it started, but 191 | # possibly modified. 192 | # 193 | # NB: a `for` loop captures its iteration list before it begins, so 194 | # changing the positional parameters here affects neither the number of 195 | # iterations, nor the values presented in `arg`. 196 | shift # remove old arg 197 | set -- "$@" "$arg" # push replacement arg 198 | done 199 | fi 200 | 201 | 202 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 203 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 204 | 205 | # Collect all arguments for the java command; 206 | # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of 207 | # shell script including quotes and variable substitutions, so put them in 208 | # double quotes to make sure that they get re-expanded; and 209 | # * put everything else in single quotes, so that it's not re-expanded. 210 | 211 | set -- \ 212 | "-Dorg.gradle.appname=$APP_BASE_NAME" \ 213 | -classpath "$CLASSPATH" \ 214 | org.gradle.wrapper.GradleWrapperMain \ 215 | "$@" 216 | 217 | # Stop when "xargs" is not available. 218 | if ! command -v xargs >/dev/null 2>&1 219 | then 220 | die "xargs is not available" 221 | fi 222 | 223 | # Use "xargs" to parse quoted args. 224 | # 225 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed. 226 | # 227 | # In Bash we could simply go: 228 | # 229 | # readarray ARGS < <( xargs -n1 <<<"$var" ) && 230 | # set -- "${ARGS[@]}" "$@" 231 | # 232 | # but POSIX shell has neither arrays nor command substitution, so instead we 233 | # post-process each arg (as a line of input to sed) to backslash-escape any 234 | # character that might be a shell metacharacter, then use eval to reverse 235 | # that process (while maintaining the separation between arguments), and wrap 236 | # the whole thing up as a single "set" statement. 237 | # 238 | # This will of course break if any of these variables contains a newline or 239 | # an unmatched quote. 240 | # 241 | 242 | eval "set -- $( 243 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | 244 | xargs -n1 | 245 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | 246 | tr '\n' ' ' 247 | )" '"$@"' 248 | 249 | exec "$JAVACMD" "$@" 250 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%"=="" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%"=="" set DIRNAME=. 29 | @rem This is normally unused 30 | set APP_BASE_NAME=%~n0 31 | set APP_HOME=%DIRNAME% 32 | 33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 35 | 36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 38 | 39 | @rem Find java.exe 40 | if defined JAVA_HOME goto findJavaFromJavaHome 41 | 42 | set JAVA_EXE=java.exe 43 | %JAVA_EXE% -version >NUL 2>&1 44 | if %ERRORLEVEL% equ 0 goto execute 45 | 46 | echo. 47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 48 | echo. 49 | echo Please set the JAVA_HOME variable in your environment to match the 50 | echo location of your Java installation. 51 | 52 | goto fail 53 | 54 | :findJavaFromJavaHome 55 | set JAVA_HOME=%JAVA_HOME:"=% 56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 57 | 58 | if exist "%JAVA_EXE%" goto execute 59 | 60 | echo. 61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 62 | echo. 63 | echo Please set the JAVA_HOME variable in your environment to match the 64 | echo location of your Java installation. 65 | 66 | goto fail 67 | 68 | :execute 69 | @rem Setup the command line 70 | 71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 72 | 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if %ERRORLEVEL% equ 0 goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | set EXIT_CODE=%ERRORLEVEL% 85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 87 | exit /b %EXIT_CODE% 88 | 89 | :mainEnd 90 | if "%OS%"=="Windows_NT" endlocal 91 | 92 | :omega 93 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | maven { 4 | name = 'Fabric' 5 | url = 'https://maven.fabricmc.net/' 6 | } 7 | mavenCentral() 8 | gradlePluginPortal() 9 | } 10 | } -------------------------------------------------------------------------------- /src/main/java/org/cmdutils/MainClient.java: -------------------------------------------------------------------------------- 1 | package org.cmdutils; 2 | 3 | import net.fabricmc.api.ClientModInitializer; 4 | import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; 5 | import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; 6 | import net.minecraft.client.option.KeyBinding; 7 | import net.minecraft.client.util.InputUtil; 8 | 9 | import java.io.IOException; 10 | 11 | import org.cmdutils.terminal.gui.InGameTerminalGui; 12 | import org.cmdutils.terminal.telnet.TelnetTerminal; 13 | import org.lwjgl.glfw.GLFW; 14 | import org.slf4j.Logger; 15 | import org.slf4j.LoggerFactory; 16 | 17 | public class MainClient implements ClientModInitializer { 18 | public static final Logger LOGGER = LoggerFactory.getLogger("cmd-utils"); 19 | 20 | public static KeyBinding terminalKey; 21 | private TelnetTerminal telnetTerminal; 22 | 23 | @Override 24 | public void onInitializeClient() { 25 | telnetTerminal = new TelnetTerminal(); 26 | new Thread(() -> { 27 | try { 28 | telnetTerminal.handleConnections(3300); 29 | } catch (IOException e) { 30 | LOGGER.error("Failed to handle telnet connections", e); 31 | } 32 | }).start(); 33 | try { 34 | System.setProperty("java.awt.headless", "false"); 35 | System.setProperty("apple.awt.contentScaleFactor", "1"); 36 | System.setProperty("apple.awt.graphics.UseQuartz", "false"); 37 | } catch (Exception e) { 38 | LOGGER.warn("Failed to initialize Swing compatibility options on startup.", e); 39 | } 40 | 41 | terminalKey = KeyBindingHelper.registerKeyBinding(new KeyBinding( 42 | "key.terminal", 43 | InputUtil.Type.KEYSYM, 44 | GLFW.GLFW_KEY_Y, 45 | "key.categories.cmdutils" 46 | )); 47 | 48 | ClientTickEvents.END_CLIENT_TICK.register((client) -> { 49 | while (terminalKey.wasPressed()) { 50 | client.setScreen(new InGameTerminalGui(null, null)); 51 | } 52 | }); 53 | } 54 | } -------------------------------------------------------------------------------- /src/main/java/org/cmdutils/ModInfo.java: -------------------------------------------------------------------------------- 1 | package org.cmdutils; 2 | 3 | public class ModInfo { 4 | public static final String VERSION = "1.0.3"; 5 | public static final String LICENSE = "GNU General Public License 3"; 6 | public static final String SOURCE = "https://github.com/Coderx-Gamer/cmd-utils/"; 7 | public static final String[] AUTHORS = { 8 | "Coderx_Gamer", 9 | "MrBreakNFix" 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/org/cmdutils/command/Command.java: -------------------------------------------------------------------------------- 1 | package org.cmdutils.command; 2 | 3 | import net.minecraft.client.MinecraftClient; 4 | import org.cmdutils.terminal.logger.Logger; 5 | 6 | public abstract class Command { 7 | public static final MinecraftClient client = MinecraftClient.getInstance(); 8 | 9 | private final String name; 10 | private final String description; 11 | private final String alias; 12 | private final String help; 13 | 14 | public Command(String name, String description, String help) { 15 | this(name, description, null, help); 16 | } 17 | 18 | public Command(String name, String description, String help, String alias) { 19 | this.name = name; 20 | this.description = description; 21 | this.help = help; 22 | this.alias = alias; 23 | 24 | } 25 | 26 | public abstract int execute(String[] args, Logger logger, CommandEnvironment env); 27 | 28 | public String getName() { 29 | return this.name; 30 | } 31 | 32 | public String getDescription() { 33 | return this.description; 34 | } 35 | 36 | public String getAlias() { 37 | return this.alias; 38 | } 39 | 40 | public String getHelp() { 41 | return this.help; 42 | } 43 | } -------------------------------------------------------------------------------- /src/main/java/org/cmdutils/command/CommandEnvironment.java: -------------------------------------------------------------------------------- 1 | package org.cmdutils.command; 2 | 3 | public enum CommandEnvironment { 4 | IN_GAME, SWING, TELNET 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/org/cmdutils/command/CommandParser.java: -------------------------------------------------------------------------------- 1 | package org.cmdutils.command; 2 | 3 | import org.cmdutils.terminal.logger.Logger; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | import java.util.regex.Matcher; 8 | import java.util.regex.Pattern; 9 | 10 | public class CommandParser { 11 | private static final Pattern COMMAND_PATTERN = Pattern.compile("\"([^\"]*)\"|\\S+"); 12 | 13 | public static RunnableCommand parseCommand(String commandString, Logger logger, CommandEnvironment env) { 14 | List tokens = tokenize(commandString); 15 | if (tokens.isEmpty()) { 16 | return null; 17 | } 18 | 19 | String commandName = tokens.get(0); 20 | Command command = findCommand(commandName); 21 | if (command == null) { 22 | return null; 23 | } 24 | 25 | List args = tokens.subList(1, tokens.size()); 26 | return new RunnableCommand(command, args.toArray(new String[0]), logger, env); 27 | } 28 | 29 | private static List tokenize(String command) { 30 | List tokens = new ArrayList<>(); 31 | Matcher matcher = COMMAND_PATTERN.matcher(command); 32 | while (matcher.find()) { 33 | String token = matcher.group(1); 34 | if (token == null) { 35 | token = matcher.group(); 36 | } 37 | tokens.add(token); 38 | } 39 | return tokens; 40 | } 41 | 42 | private static Command findCommand(String name) { 43 | Command command = Commands.find(name); 44 | if (command == null) { 45 | for (Command cmd : Commands.COMMANDS) { 46 | if (cmd.getAlias() != null && cmd.getAlias().equals(name)) { 47 | command = cmd; 48 | break; 49 | } 50 | } 51 | } 52 | return command; 53 | } 54 | } -------------------------------------------------------------------------------- /src/main/java/org/cmdutils/command/Commands.java: -------------------------------------------------------------------------------- 1 | package org.cmdutils.command; 2 | 3 | import org.cmdutils.command.commands.*; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | public class Commands { 9 | public static final int COMMAND_SUCCESS = 0; 10 | public static final int COMMAND_FAILURE = 1; 11 | 12 | public static final List COMMANDS = new ArrayList<>(); 13 | 14 | public static void registerCommand(Command command) { 15 | COMMANDS.add(command); 16 | } 17 | 18 | public static Command find(String name) { 19 | for (Command command : COMMANDS) { 20 | if (command.getName().equals(name)) { 21 | return command; 22 | } 23 | } 24 | return null; 25 | } 26 | 27 | static { 28 | registerCommand(new ClearCommand()); 29 | registerCommand(new HelpCommand()); 30 | registerCommand(new CmdUtilsCommand()); 31 | registerCommand(new SwingCommand()); 32 | registerCommand(new CloseCommand()); 33 | registerCommand(new DeSyncCommand()); 34 | registerCommand(new MenuInfoCommand()); 35 | registerCommand(new SaveGuiCommand()); 36 | registerCommand(new RestoreGuiCommand()); 37 | registerCommand(new LeaveCommand()); 38 | registerCommand(new WakeCommand()); 39 | registerCommand(new McfwCommand()); 40 | registerCommand(new RPackCommand()); 41 | registerCommand(new SessionCommand()); 42 | registerCommand(new ChatCommand()); 43 | registerCommand(new ClickCommand()); 44 | registerCommand(new ButtonCommand()); 45 | registerCommand(new TradeCommand()); 46 | registerCommand(new LoopCommand()); 47 | registerCommand(new DropCommand()); 48 | registerCommand(new CrashCommand()); 49 | registerCommand(new BashCommand()); 50 | registerCommand(new SlashCommand()); 51 | // registerCommand(new RespawnCommand()); 52 | // registerCommand(new JoinServerCommand()); 53 | // registerCommand(new QuitGameCommand()); // pov too lazy to press "Quit Game" 54 | 55 | 56 | 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/org/cmdutils/command/RunnableCommand.java: -------------------------------------------------------------------------------- 1 | package org.cmdutils.command; 2 | 3 | import org.cmdutils.terminal.logger.Logger; 4 | 5 | public record RunnableCommand(Command command, String[] args, Logger logger, CommandEnvironment env) { 6 | public int execute() { 7 | return this.command().execute(this.args(), this.logger(), this.env()); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/org/cmdutils/command/commands/BashCommand.java: -------------------------------------------------------------------------------- 1 | package org.cmdutils.command.commands; 2 | 3 | import org.cmdutils.command.Command; 4 | import org.cmdutils.command.CommandEnvironment; 5 | import org.cmdutils.command.Commands; 6 | import org.cmdutils.terminal.logger.Logger; 7 | 8 | import java.io.BufferedReader; 9 | import java.io.IOException; 10 | import java.io.InputStreamReader; 11 | 12 | public class BashCommand extends Command { 13 | public BashCommand() { 14 | super("bash", "Executes a Bash command. Alias: \"$\"", "Syntax: \"bash\"/\"/\" args0[UNIX bash command]\nArguments are accepted, but commands currently run forever. be careful\nExample: \"$ ls /\"", "$"); 15 | } 16 | 17 | @Override 18 | public int execute(String[] args, Logger logger, CommandEnvironment env) { 19 | String osName = System.getProperty("os.name").toLowerCase(); 20 | if (!osName.contains("nix") && !osName.contains("nux") && !osName.contains("aix")) { 21 | logger.error("Bash commands are only supported on Unix-like systems."); 22 | return Commands.COMMAND_FAILURE; 23 | } 24 | 25 | if (args.length == 0) { 26 | logger.error("Usage: \"bash \" OR \"$ \""); 27 | return Commands.COMMAND_FAILURE; 28 | } 29 | 30 | String command = String.join(" ", args); 31 | 32 | try { 33 | Thread commandThread = new Thread(() -> { 34 | try { 35 | Process process = Runtime.getRuntime().exec(new String[]{"bash", "-c", command}); 36 | BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); 37 | String line; 38 | while ((line = reader.readLine()) != null) { 39 | logger.info(line); 40 | } 41 | process.waitFor(); 42 | reader.close(); 43 | } catch (IOException | InterruptedException e) { 44 | logger.error("Error executing Bash command: " + e.getMessage()); 45 | } 46 | }); 47 | 48 | commandThread.start(); 49 | 50 | commandThread.join(15000); 51 | 52 | if (commandThread.isAlive()) { 53 | logger.error("Bash command execution timed out after 15 seconds."); 54 | commandThread.interrupt(); 55 | return Commands.COMMAND_FAILURE; 56 | } else { 57 | // logger.info("Bash command executed successfully."); 58 | return Commands.COMMAND_SUCCESS; 59 | } 60 | } catch (InterruptedException e) { 61 | logger.error("Error executing Bash command: " + e.getMessage()); 62 | return Commands.COMMAND_FAILURE; 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /src/main/java/org/cmdutils/command/commands/ButtonCommand.java: -------------------------------------------------------------------------------- 1 | package org.cmdutils.command.commands; 2 | 3 | import net.minecraft.network.packet.c2s.play.ButtonClickC2SPacket; 4 | import net.minecraft.screen.ScreenHandler; 5 | import org.cmdutils.command.Command; 6 | import org.cmdutils.command.CommandEnvironment; 7 | import org.cmdutils.command.Commands; 8 | import org.cmdutils.terminal.gui.InGameTerminalGui; 9 | import org.cmdutils.terminal.logger.Logger; 10 | import org.cmdutils.util.Utils; 11 | 12 | public class ButtonCommand extends Command { 13 | public ButtonCommand() { 14 | super("button", "Send a ButtonClick packet.", "Syntax: \"button\" args0[SyncID / current] args1[button (int)]", null); 15 | } 16 | 17 | @Override 18 | public int execute(String[] args, Logger logger, CommandEnvironment env) { 19 | if (args.length != 2) { 20 | logger.error("Invalid Arguments."); 21 | return Commands.COMMAND_FAILURE; 22 | } 23 | 24 | ScreenHandler handler; 25 | 26 | if (env == CommandEnvironment.IN_GAME && client.currentScreen instanceof InGameTerminalGui gui) { 27 | handler = gui.previousScreenHandler; 28 | } else { 29 | if (client.player != null && client.player.currentScreenHandler != null) { 30 | handler = client.player.currentScreenHandler; 31 | } else { 32 | handler = null; 33 | } 34 | } 35 | 36 | if (client.getNetworkHandler() == null) { 37 | logger.error("You are not connected to a server."); 38 | return Commands.COMMAND_FAILURE; 39 | } 40 | 41 | if (handler == null) { 42 | logger.error("You do not have a HandledScreen open."); 43 | return Commands.COMMAND_FAILURE; 44 | } 45 | 46 | Integer syncId; 47 | Integer button = Utils.toInteger(args[1]); 48 | 49 | if (args[0].equals("current")) { 50 | syncId = handler.syncId; 51 | } else { 52 | syncId = Utils.toInteger(args[0]); 53 | } 54 | 55 | if (syncId == null) { 56 | logger.error("Invalid Sync ID."); 57 | return Commands.COMMAND_FAILURE; 58 | } 59 | 60 | if (button == null) { 61 | logger.error("Invalid Button."); 62 | return Commands.COMMAND_FAILURE; 63 | } 64 | 65 | client.getNetworkHandler().sendPacket(new ButtonClickC2SPacket(syncId, button)); 66 | logger.info("Sent ButtonClick packet."); 67 | 68 | return Commands.COMMAND_SUCCESS; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/org/cmdutils/command/commands/ChatCommand.java: -------------------------------------------------------------------------------- 1 | package org.cmdutils.command.commands; 2 | 3 | import org.cmdutils.command.Command; 4 | import org.cmdutils.command.CommandEnvironment; 5 | import org.cmdutils.command.Commands; 6 | import org.cmdutils.terminal.logger.Logger; 7 | 8 | public class ChatCommand extends Command { 9 | public ChatCommand() { 10 | super("chat", "Send chat message, use \"/\" to execute commands instead.", "Syntax: \"chat args0[\"Text in spaces w/ double quotes\"]\"\nor, \"chat args0[noSpacesNoQuotes]\"", null); 11 | } 12 | 13 | @Override 14 | public int execute(String[] args, Logger logger, CommandEnvironment env) { 15 | if (client.getNetworkHandler() == null) { 16 | logger.error("You are not connected to a server."); 17 | return Commands.COMMAND_FAILURE; 18 | } 19 | 20 | if (args.length == 1) { 21 | client.getNetworkHandler().sendChatMessage(args[0]); 22 | logger.info("Sent chat message."); 23 | return Commands.COMMAND_SUCCESS; 24 | } 25 | 26 | logger.error("Invalid Arguments."); 27 | 28 | return Commands.COMMAND_FAILURE; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/org/cmdutils/command/commands/ClearCommand.java: -------------------------------------------------------------------------------- 1 | package org.cmdutils.command.commands; 2 | 3 | import org.cmdutils.command.Command; 4 | import org.cmdutils.command.CommandEnvironment; 5 | import org.cmdutils.command.Commands; 6 | import org.cmdutils.terminal.logger.Logger; 7 | 8 | public class ClearCommand extends Command { 9 | public ClearCommand() { 10 | super("clear", "Clear the log.", "No arguments", null); 11 | } 12 | 13 | @Override 14 | public int execute(String[] args, Logger logger, CommandEnvironment env) { 15 | if (logger.canClear()) { 16 | logger.clear(); 17 | return Commands.COMMAND_SUCCESS; 18 | } else { 19 | logger.error("Clearing Not Supported."); 20 | return Commands.COMMAND_FAILURE; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/org/cmdutils/command/commands/ClickCommand.java: -------------------------------------------------------------------------------- 1 | package org.cmdutils.command.commands; 2 | 3 | import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap; 4 | import net.minecraft.item.ItemStack; 5 | import net.minecraft.network.packet.c2s.play.ClickSlotC2SPacket; 6 | import net.minecraft.screen.ScreenHandler; 7 | import net.minecraft.screen.slot.SlotActionType; 8 | import org.cmdutils.command.Command; 9 | import org.cmdutils.command.CommandEnvironment; 10 | import org.cmdutils.command.Commands; 11 | import org.cmdutils.terminal.gui.InGameTerminalGui; 12 | import org.cmdutils.terminal.logger.Logger; 13 | import org.cmdutils.util.Utils; 14 | 15 | public class ClickCommand extends Command { 16 | public ClickCommand() { 17 | super("click", "Send a ClickSlot packet.", "Syntax: \"click args0[SyncID(int) OR \"current\"] args1[Revision(int) OR \"current\"] args2[Slot (int)] args3[Button (int)] args4[SlotActionType (pickup, quick-move, swap, clone, throw, quick-craft, pickup-all)]\"\n Example: \"click current current 1 2 swap\" (untested example)",null); 18 | } 19 | 20 | @Override 21 | public int execute(String[] args, Logger logger, CommandEnvironment env) { 22 | if (args.length != 5) { 23 | logger.error("Invalid Arguments."); 24 | return Commands.COMMAND_FAILURE; 25 | } 26 | 27 | ScreenHandler handler; 28 | 29 | if (env == CommandEnvironment.IN_GAME && client.currentScreen instanceof InGameTerminalGui gui) { 30 | handler = gui.previousScreenHandler; 31 | } else { 32 | if (client.player != null && client.player.currentScreenHandler != null) { 33 | handler = client.player.currentScreenHandler; 34 | } else { 35 | handler = null; 36 | } 37 | } 38 | 39 | if (client.getNetworkHandler() == null) { 40 | logger.error("You are not connected to a server."); 41 | return Commands.COMMAND_FAILURE; 42 | } 43 | 44 | if (handler == null) { 45 | logger.error("You do not have a HandledScreen open."); 46 | return Commands.COMMAND_FAILURE; 47 | } 48 | 49 | Integer syncId; 50 | Integer revision; 51 | Integer slot = Utils.toInteger(args[2]); 52 | Integer button = Utils.toInteger(args[3]); 53 | SlotActionType type = switch (args[4]) { 54 | case "pickup" -> SlotActionType.PICKUP; 55 | case "quick-move" -> SlotActionType.QUICK_MOVE; 56 | case "swap" -> SlotActionType.SWAP; 57 | case "clone" -> SlotActionType.CLONE; 58 | case "throw" -> SlotActionType.THROW; 59 | case "quick-craft" -> SlotActionType.QUICK_CRAFT; 60 | case "pickup-all" -> SlotActionType.PICKUP_ALL; 61 | default -> null; 62 | }; 63 | 64 | if (slot == null) { 65 | logger.error("Invalid Slot."); 66 | return Commands.COMMAND_FAILURE; 67 | } 68 | 69 | if (button == null) { 70 | logger.error("Invalid Button."); 71 | return Commands.COMMAND_FAILURE; 72 | } 73 | 74 | if (type == null) { 75 | logger.error("Invalid Action Type."); 76 | return Commands.COMMAND_FAILURE; 77 | } 78 | 79 | if (args[0].equals("current")) { 80 | syncId = handler.syncId; 81 | } else { 82 | syncId = Utils.toInteger(args[0]); 83 | } 84 | 85 | if (args[1].equals("current")) { 86 | revision = handler.getRevision(); 87 | } else { 88 | revision = Utils.toInteger(args[1]); 89 | } 90 | 91 | if (syncId == null) { 92 | logger.error("Invalid Sync ID."); 93 | return Commands.COMMAND_FAILURE; 94 | } 95 | 96 | if (revision == null) { 97 | logger.error("Invalid Revision."); 98 | return Commands.COMMAND_FAILURE; 99 | } 100 | 101 | client.getNetworkHandler().sendPacket(new ClickSlotC2SPacket(syncId, revision, slot, button, type, ItemStack.EMPTY, new Int2ObjectArrayMap<>())); 102 | logger.info("Sent ClickSlot packet."); 103 | 104 | return Commands.COMMAND_SUCCESS; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/main/java/org/cmdutils/command/commands/CloseCommand.java: -------------------------------------------------------------------------------- 1 | package org.cmdutils.command.commands; 2 | 3 | import org.cmdutils.command.Command; 4 | import org.cmdutils.command.CommandEnvironment; 5 | import org.cmdutils.command.Commands; 6 | import org.cmdutils.terminal.logger.Logger; 7 | 8 | public class CloseCommand extends Command { 9 | public CloseCommand() { 10 | super("close", "Close current GUI without sending a GUI close packet.", "Use this to keep stuff open server-side",null); 11 | } 12 | 13 | @Override 14 | public int execute(String[] args, Logger logger, CommandEnvironment env) { 15 | if (args.length != 0) { 16 | logger.error("Invalid Arguments, usage: 'close'."); 17 | return Commands.COMMAND_FAILURE; 18 | } 19 | 20 | client.setScreen(null); 21 | 22 | return Commands.COMMAND_SUCCESS; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/cmdutils/command/commands/CmdUtilsCommand.java: -------------------------------------------------------------------------------- 1 | package org.cmdutils.command.commands; 2 | 3 | import org.cmdutils.ModInfo; 4 | import org.cmdutils.command.Command; 5 | import org.cmdutils.command.CommandEnvironment; 6 | import org.cmdutils.command.Commands; 7 | import org.cmdutils.terminal.logger.Logger; 8 | 9 | public class CmdUtilsCommand extends Command { 10 | public CmdUtilsCommand() { 11 | super("cmdutils", "Shows CMD Utils information.", "Reach out to authors for issues or help",null); 12 | } 13 | 14 | @Override 15 | public int execute(String[] args, Logger logger, CommandEnvironment env) { 16 | if (args.length != 0) { 17 | logger.error("Invalid Arguments, usage: 'cmdutils'."); 18 | return Commands.COMMAND_FAILURE; 19 | } 20 | 21 | logger.println("CMD-Utils " + ModInfo.VERSION + '\n'); 22 | logger.println("License: " + ModInfo.LICENSE); 23 | logger.println("Source: " + ModInfo.SOURCE); 24 | logger.println("Authors:"); 25 | 26 | for (String author : ModInfo.AUTHORS) { 27 | logger.println("- " + author); 28 | } 29 | 30 | return Commands.COMMAND_SUCCESS; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/org/cmdutils/command/commands/CrashCommand.java: -------------------------------------------------------------------------------- 1 | package org.cmdutils.command.commands; 2 | 3 | import org.cmdutils.command.Command; 4 | import org.cmdutils.command.CommandEnvironment; 5 | import org.cmdutils.command.Commands; 6 | import org.cmdutils.terminal.logger.Logger; 7 | 8 | public class CrashCommand extends Command { 9 | public CrashCommand() { 10 | super("crash", "Forcefully crashes the game without java shutdown hook events executing.", "You can use this for duping in singleplayer instead of using task manager",null); 11 | } 12 | 13 | @Override 14 | public int execute(String[] args, Logger logger, CommandEnvironment env) { 15 | String osName = System.getProperty("os.name").toLowerCase(); 16 | 17 | if (osName.contains("win")) { 18 | executeWindows(logger); 19 | } else if (osName.contains("nix") || osName.contains("nux") || osName.contains("aix")) { 20 | executeLinux(logger); 21 | } else if (osName.contains("mac")) { 22 | executeMac(logger); 23 | } else { 24 | logger.error("Unsupported operating system."); 25 | return Commands.COMMAND_FAILURE; 26 | } 27 | 28 | return Commands.COMMAND_SUCCESS; 29 | } 30 | 31 | private void executeWindows(Logger logger) { 32 | try { 33 | Runtime.getRuntime().exec("taskkill /f /im java.exe"); 34 | logger.info("Java process forcefully terminated on Windows."); 35 | } catch (Exception e) { 36 | logger.error("Error occurred while trying to terminate the Java process on Windows."); 37 | } 38 | } 39 | 40 | private void executeLinux(Logger logger) { 41 | try { 42 | Runtime.getRuntime().exec("pkill -9 java"); 43 | logger.info("Java process forcefully terminated on Linux."); 44 | } catch (Exception e) { 45 | logger.error("Error occurred while trying to terminate the Java process on Linux."); 46 | } 47 | } 48 | 49 | private void executeMac(Logger logger) { 50 | try { 51 | Runtime.getRuntime().exec("pkill -9 java"); 52 | logger.info("Java process forcefully terminated on macOS."); 53 | } catch (Exception e) { 54 | logger.error("Error occurred while trying to terminate the Java process on macOS."); 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /src/main/java/org/cmdutils/command/commands/DeSyncCommand.java: -------------------------------------------------------------------------------- 1 | package org.cmdutils.command.commands; 2 | 3 | import net.minecraft.network.packet.c2s.play.CloseHandledScreenC2SPacket; 4 | import org.cmdutils.command.Command; 5 | import org.cmdutils.command.CommandEnvironment; 6 | import org.cmdutils.command.Commands; 7 | import org.cmdutils.terminal.gui.InGameTerminalGui; 8 | import org.cmdutils.terminal.logger.Logger; 9 | 10 | public class DeSyncCommand extends Command { 11 | public DeSyncCommand() { 12 | super("desync", "Send a GUI close packet without closing your client-side GUI.", "Be connected to a server with a HandledScreen, like a chest, open",null); 13 | } 14 | 15 | @Override 16 | public int execute(String[] args, Logger logger, CommandEnvironment env) { 17 | if (args.length != 0) { 18 | logger.error("Invalid Arguments, usage: 'desync'."); 19 | return Commands.COMMAND_FAILURE; 20 | } 21 | 22 | int syncId; 23 | 24 | if (env == CommandEnvironment.IN_GAME && client.currentScreen instanceof InGameTerminalGui gui) { 25 | if (gui.previousScreenHandler == null) { 26 | logger.error("You have no HandledScreen (container) open."); 27 | return Commands.COMMAND_FAILURE; 28 | } 29 | 30 | syncId = gui.previousScreenHandler.syncId; 31 | } else { 32 | if (client.player == null) { 33 | logger.error("You are not connected to a server."); 34 | return Commands.COMMAND_FAILURE; 35 | } 36 | 37 | if (client.player.currentScreenHandler == null) { 38 | logger.error("You have no HandledScreen (container) open."); 39 | return Commands.COMMAND_FAILURE; 40 | } 41 | 42 | syncId = client.player.currentScreenHandler.syncId; 43 | } 44 | 45 | if (client.getNetworkHandler() == null) { 46 | logger.error("You are not connected to a server."); 47 | return Commands.COMMAND_FAILURE; 48 | } 49 | 50 | client.getNetworkHandler().sendPacket(new CloseHandledScreenC2SPacket(syncId)); 51 | logger.info("De-sync successful."); 52 | 53 | return Commands.COMMAND_SUCCESS; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/org/cmdutils/command/commands/DropCommand.java: -------------------------------------------------------------------------------- 1 | package org.cmdutils.command.commands; 2 | 3 | import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket; 4 | import net.minecraft.util.math.BlockPos; 5 | import net.minecraft.util.math.Direction; 6 | import org.cmdutils.command.Command; 7 | import org.cmdutils.command.CommandEnvironment; 8 | import org.cmdutils.command.Commands; 9 | import org.cmdutils.terminal.logger.Logger; 10 | 11 | public class DropCommand extends Command { 12 | public DropCommand() { 13 | super("drop", "Drop an item in your hotbar.", "Syntax: \"drop args0[\"all\"] -- OPTIONAL",null); 14 | } 15 | 16 | @Override 17 | public int execute(String[] args, Logger logger, CommandEnvironment env) { 18 | if (!(client.getNetworkHandler() != null && client.player != null)) { 19 | logger.error("You are not connected to a server."); 20 | return Commands.COMMAND_FAILURE; 21 | } 22 | 23 | if (args.length == 0) { 24 | client.getNetworkHandler().sendPacket(new PlayerActionC2SPacket(PlayerActionC2SPacket.Action.DROP_ITEM, BlockPos.ORIGIN, Direction.DOWN)); 25 | logger.info("Sent PlayerAction packet."); 26 | return Commands.COMMAND_SUCCESS; 27 | } 28 | 29 | if (args.length == 1) { 30 | if (!args[0].equals("all")) { 31 | logger.error("Invalid Arguments."); 32 | return Commands.COMMAND_FAILURE; 33 | } 34 | 35 | client.getNetworkHandler().sendPacket(new PlayerActionC2SPacket(PlayerActionC2SPacket.Action.DROP_ALL_ITEMS, BlockPos.ORIGIN, Direction.DOWN)); 36 | logger.info("Sent PlayerAction packet."); 37 | return Commands.COMMAND_SUCCESS; 38 | } 39 | 40 | logger.error("Invalid Arguments."); 41 | 42 | return Commands.COMMAND_FAILURE; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/org/cmdutils/command/commands/HelpCommand.java: -------------------------------------------------------------------------------- 1 | package org.cmdutils.command.commands; 2 | 3 | import org.cmdutils.command.Command; 4 | import org.cmdutils.command.CommandEnvironment; 5 | import org.cmdutils.command.Commands; 6 | import org.cmdutils.terminal.logger.Logger; 7 | 8 | public class HelpCommand extends Command { 9 | public HelpCommand() { 10 | super("help", "Shows a list of commands.", "Syntax: \"help args0[command] -- OPTIONAL", null); 11 | } 12 | 13 | 14 | //todo (mrbreak): help argument correction 15 | @Override 16 | public int execute(String[] args, Logger logger, CommandEnvironment env) { 17 | if (args.length != 0 && args.length != 1) { 18 | logger.error("Invalid Arguments, usage: 'help'."); 19 | return Commands.COMMAND_FAILURE; 20 | } 21 | 22 | if (args.length == 0) { 23 | logger.println("List of commands:\n"); 24 | 25 | for (Command command : Commands.COMMANDS) { 26 | logger.println("- " + command.getName() + ": " + command.getDescription()); 27 | } 28 | } else { 29 | Command command = Commands.find(args[0]); 30 | if (command == null) { 31 | logger.error("Help: Unknown Command."); 32 | return Commands.COMMAND_FAILURE; 33 | } 34 | 35 | logger.info("Description: " + command.getDescription()); 36 | logger.info("Help: " + command.getHelp()); 37 | } 38 | 39 | return Commands.COMMAND_SUCCESS; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/org/cmdutils/command/commands/LeaveCommand.java: -------------------------------------------------------------------------------- 1 | package org.cmdutils.command.commands; 2 | 3 | import net.minecraft.client.gui.screen.DisconnectedScreen; 4 | import net.minecraft.text.Text; 5 | import org.cmdutils.command.Command; 6 | import org.cmdutils.command.CommandEnvironment; 7 | import org.cmdutils.command.Commands; 8 | import org.cmdutils.terminal.logger.Logger; 9 | 10 | public class LeaveCommand extends Command { 11 | public LeaveCommand() { 12 | super("leave", "Leave the server.", "Just be on a server / in a world before doing this.",null); 13 | } 14 | 15 | @Override 16 | public int execute(String[] args, Logger logger, CommandEnvironment env) { 17 | if (args.length != 0) { 18 | logger.error("Invalid Arguments, usage: 'leave'."); 19 | return Commands.COMMAND_FAILURE; 20 | } 21 | 22 | if (client.getNetworkHandler() == null || client.world == null) { 23 | logger.error("You are not connected to a server."); 24 | return Commands.COMMAND_FAILURE; 25 | } 26 | 27 | client.world.disconnect(); 28 | client.disconnect(); 29 | client.setScreen(new DisconnectedScreen(null, Text.of("Disconnected"), Text.of("Disconnected by CMD-Utils"))); 30 | 31 | return Commands.COMMAND_SUCCESS; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/org/cmdutils/command/commands/LoopCommand.java: -------------------------------------------------------------------------------- 1 | package org.cmdutils.command.commands; 2 | 3 | import org.cmdutils.command.Command; 4 | import org.cmdutils.command.CommandEnvironment; 5 | import org.cmdutils.command.Commands; 6 | import org.cmdutils.command.RunnableCommand; 7 | import org.cmdutils.terminal.logger.Logger; 8 | import org.cmdutils.terminal.logger.NullLogger; 9 | import org.cmdutils.util.Utils; 10 | 11 | import java.util.Arrays; 12 | 13 | public class LoopCommand extends Command { 14 | public LoopCommand() { 15 | super("loop", "Loop a command any amount of times.", "Syntax: \"loop args0[commandName] argumentsOfCommandIfNeeded[]... -- OPTIONAL\"",null); 16 | } 17 | 18 | @Override 19 | public int execute(String[] args, Logger logger, CommandEnvironment env) { 20 | if (args.length < 2) { 21 | logger.error("Invalid Loop Arguments."); 22 | return Commands.COMMAND_FAILURE; 23 | } 24 | 25 | Integer times = Utils.toInteger(args[0]); 26 | 27 | if (times == null) { 28 | logger.error("Invalid Loop Count."); 29 | return Commands.COMMAND_FAILURE; 30 | } 31 | 32 | NullLogger nullLogger = new NullLogger(); 33 | for (int i = 0; i < times; i++) { 34 | new RunnableCommand(Commands.find(args[1]), args.length == 2 ? new String[0] : Arrays.copyOfRange(args, 2, args.length), nullLogger, env).execute(); 35 | } 36 | 37 | logger.info("Finished loop."); 38 | 39 | return Commands.COMMAND_SUCCESS; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/org/cmdutils/command/commands/McfwCommand.java: -------------------------------------------------------------------------------- 1 | package org.cmdutils.command.commands; 2 | 3 | import net.minecraft.network.packet.Packet; 4 | import org.cmdutils.command.Command; 5 | import org.cmdutils.command.CommandEnvironment; 6 | import org.cmdutils.command.Commands; 7 | import org.cmdutils.terminal.logger.Logger; 8 | import org.cmdutils.util.ClassMap; 9 | import org.cmdutils.util.Mcfw; 10 | import org.cmdutils.util.McfwFilterType; 11 | 12 | public class McfwCommand extends Command { 13 | public McfwCommand() { 14 | super("mcfw", "Minecraft Firewall packet filter.", "Syntax: \"mcfw args0[quiet-disable, drops packets / status (returns if on or off) / list (lists packets filtered) / delayed (lists amount of delayed packets) / clear (clears packets) / clear-delayed (guess) / block/delay/remove] args1[if args0 was block delay or remove, then this is the type of packet (packet?)]\"",null); 15 | } 16 | 17 | @Override 18 | public int execute(String[] args, Logger logger, CommandEnvironment env) { 19 | if (args.length == 1) { 20 | if (args[0].equals("enable")) { 21 | Mcfw.enabled = true; 22 | logger.info("Enabled MCFW."); 23 | return Commands.COMMAND_SUCCESS; 24 | } 25 | 26 | if (args[0].equals("disable")) { 27 | if (client.getNetworkHandler() == null) { 28 | logger.error("You are not connected to a server, use quiet-disable instead."); 29 | return Commands.COMMAND_FAILURE; 30 | } 31 | Mcfw.enabled = false; 32 | for (Packet packet : Mcfw.delayedPackets) { 33 | client.getNetworkHandler().sendPacket(packet); 34 | } 35 | 36 | logger.info("Disabled MCFW and sent " + Mcfw.delayedPackets.size() + " packets."); 37 | Mcfw.delayedPackets.clear(); 38 | return Commands.COMMAND_SUCCESS; 39 | } 40 | 41 | if (args[0].equals("quiet-disable")) { 42 | Mcfw.enabled = false; 43 | logger.info("Disabled MCFW without sending delayed packets."); 44 | Mcfw.delayedPackets.clear(); 45 | return Commands.COMMAND_SUCCESS; 46 | } 47 | 48 | if (args[0].equals("status")) { 49 | logger.info("MCFW is " + (Mcfw.enabled ? "enabled" : "disabled") + "."); 50 | return Commands.COMMAND_SUCCESS; 51 | } 52 | 53 | if (args[0].equals("list")) { 54 | if (Mcfw.filteredPackets.isEmpty()) { 55 | logger.info("There are no filtered packets."); 56 | return Commands.COMMAND_SUCCESS; 57 | } 58 | 59 | logger.println("MCFW Filter:"); 60 | for (String packet : Mcfw.filteredPackets.keySet()) { 61 | logger.println("- " + packet + ": " + Mcfw.filteredPackets.get(packet).toString()); 62 | } 63 | return Commands.COMMAND_SUCCESS; 64 | } 65 | 66 | if (args[0].equals("delayed")) { 67 | if (Mcfw.enabled) { 68 | logger.info("You have " + Mcfw.delayedPackets.size() + " delayed packets."); 69 | return Commands.COMMAND_SUCCESS; 70 | } else { 71 | logger.error("MCFW is not enabled."); 72 | return Commands.COMMAND_FAILURE; 73 | } 74 | } 75 | 76 | if (args[0].equals("clear")) { 77 | Mcfw.filteredPackets.clear(); 78 | logger.info("Cleared packet filter."); 79 | return Commands.COMMAND_SUCCESS; 80 | } 81 | 82 | if (args[0].equals("clear-delayed")) { 83 | if (Mcfw.enabled) { 84 | Mcfw.delayedPackets.clear(); 85 | logger.info("Cleared delayed packets."); 86 | return Commands.COMMAND_SUCCESS; 87 | } else { 88 | logger.error("MCFW is not enabled."); 89 | return Commands.COMMAND_FAILURE; 90 | } 91 | } 92 | 93 | logger.error("Invalid MCFW Operation."); 94 | 95 | return Commands.COMMAND_FAILURE; 96 | } 97 | 98 | if (args.length == 2) { 99 | if (args[0].equals("block")) { 100 | if (ClassMap.PACKET_MAP.containsValue(args[1]) || args[1].equals("all")) { 101 | Mcfw.filteredPackets.put(args[1], McfwFilterType.BLOCKED); 102 | logger.info("Added " + args[1] + " to block list."); 103 | return Commands.COMMAND_SUCCESS; 104 | } else { 105 | logger.error("Invalid MCFW Packet."); 106 | return Commands.COMMAND_FAILURE; 107 | } 108 | } 109 | 110 | if (args[0].equals("delay")) { 111 | if (ClassMap.PACKET_MAP.containsValue(args[1]) || args[1].equals("all")) { 112 | Mcfw.filteredPackets.put(args[1], McfwFilterType.DELAYED); 113 | logger.info("Added " + args[1] + " to delay list."); 114 | return Commands.COMMAND_SUCCESS; 115 | } else { 116 | logger.error("Invalid MCFW Packet."); 117 | return Commands.COMMAND_FAILURE; 118 | } 119 | } 120 | 121 | if (args[0].equals("remove")) { 122 | McfwFilterType type = Mcfw.filteredPackets.remove(args[1]); 123 | if (type == null) { 124 | logger.error("Packet Not In Filter."); 125 | return Commands.COMMAND_FAILURE; 126 | } 127 | 128 | logger.info("Removed " + args[1] + " from " + (type == McfwFilterType.BLOCKED ? "block" : "delay") + " list."); 129 | return Commands.COMMAND_SUCCESS; 130 | } 131 | 132 | logger.error("Invalid MCFW Operation."); 133 | 134 | return Commands.COMMAND_FAILURE; 135 | } 136 | 137 | logger.error("Invalid Arguments."); 138 | 139 | return Commands.COMMAND_FAILURE; 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /src/main/java/org/cmdutils/command/commands/MenuInfoCommand.java: -------------------------------------------------------------------------------- 1 | package org.cmdutils.command.commands; 2 | 3 | import com.google.gson.JsonSerializationContext; 4 | import net.minecraft.client.gui.screen.Screen; 5 | import net.minecraft.screen.ScreenHandler; 6 | import net.minecraft.text.Text; 7 | import org.cmdutils.command.Command; 8 | import org.cmdutils.command.CommandEnvironment; 9 | import org.cmdutils.command.Commands; 10 | import org.cmdutils.terminal.gui.InGameTerminalGui; 11 | import org.cmdutils.terminal.logger.Logger; 12 | 13 | public class MenuInfoCommand extends Command { 14 | public MenuInfoCommand() { 15 | // todo: get MenuInfo to actually do something 16 | super("menuinfo", "Shows details of your current screen.", "honestly i never got this to work, gl mate!",null); 17 | } 18 | 19 | @Override 20 | public int execute(String[] args, Logger logger, CommandEnvironment env) { 21 | if (args.length != 0) { 22 | logger.error("Invalid Arguments, usage: 'menuinfo'."); 23 | return Commands.COMMAND_FAILURE; 24 | } 25 | 26 | Screen screen = null; 27 | ScreenHandler handler = null; 28 | 29 | if (env == CommandEnvironment.IN_GAME && client.currentScreen instanceof InGameTerminalGui gui) { 30 | screen = gui.previousScreen; 31 | handler = gui.previousScreenHandler; 32 | } 33 | 34 | if (env == CommandEnvironment.SWING) { 35 | screen = client.currentScreen; 36 | if (client.player != null) { 37 | handler = client.player.currentScreenHandler; 38 | } 39 | } 40 | 41 | if (screen == null) { 42 | logger.warn("Screen is null.\n"); 43 | } else { 44 | logger.info("Screen\n"); 45 | logger.info("Title JSON: " + Text.Serialization.toJsonString(screen.getTitle())); 46 | logger.info("Width: " + screen.width); 47 | logger.info("Height: " + screen.height + '\n'); 48 | } 49 | 50 | if (handler == null) { 51 | logger.warn("ScreenHandler is null.\n"); 52 | } else { 53 | logger.info("ScreenHandler\n"); 54 | logger.info("Sync ID: " + handler.syncId); 55 | logger.info("Revision: " + handler.getRevision()); 56 | logger.info("Slots: " + handler.slots.size() + '\n'); 57 | } 58 | 59 | return Commands.COMMAND_SUCCESS; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/org/cmdutils/command/commands/RPackCommand.java: -------------------------------------------------------------------------------- 1 | package org.cmdutils.command.commands; 2 | 3 | import net.minecraft.network.packet.c2s.common.ResourcePackStatusC2SPacket; 4 | import org.cmdutils.command.Command; 5 | import org.cmdutils.command.CommandEnvironment; 6 | import org.cmdutils.command.Commands; 7 | import org.cmdutils.terminal.logger.Logger; 8 | 9 | import java.util.UUID; 10 | 11 | public class RPackCommand extends Command { 12 | public RPackCommand() { 13 | super("rpack", "Resource pack bypass tool.", "Syntax: \"rpack args0[accepted/loaded/declined/failed]\" ",null); 14 | } 15 | 16 | @Override 17 | public int execute(String[] args, Logger logger, CommandEnvironment env) { 18 | if (args.length != 1) { 19 | logger.error("Invalid Arguments."); 20 | return Commands.COMMAND_FAILURE; 21 | } 22 | 23 | if (client.getNetworkHandler() == null) { 24 | logger.error("You are not connected to a server."); 25 | return Commands.COMMAND_FAILURE; 26 | } 27 | 28 | ResourcePackStatusC2SPacket.Status status = switch (args[0]) { 29 | case "accepted" -> ResourcePackStatusC2SPacket.Status.ACCEPTED; 30 | case "loaded" -> ResourcePackStatusC2SPacket.Status.SUCCESSFULLY_LOADED; 31 | case "declined" -> ResourcePackStatusC2SPacket.Status.DECLINED; 32 | case "failed" -> ResourcePackStatusC2SPacket.Status.FAILED_DOWNLOAD; 33 | default -> null; 34 | }; 35 | 36 | if (status == null) { 37 | logger.error("Invalid resource pack status."); 38 | return Commands.COMMAND_FAILURE; 39 | } 40 | 41 | client.getNetworkHandler().sendPacket(new ResourcePackStatusC2SPacket(client.getSession().getUuidOrNull(), status)); 42 | 43 | logger.info("Sent resource pack status."); 44 | 45 | return Commands.COMMAND_SUCCESS; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/org/cmdutils/command/commands/RestoreGuiCommand.java: -------------------------------------------------------------------------------- 1 | package org.cmdutils.command.commands; 2 | 3 | import org.cmdutils.command.Command; 4 | import org.cmdutils.command.CommandEnvironment; 5 | import org.cmdutils.command.Commands; 6 | import org.cmdutils.terminal.logger.Logger; 7 | 8 | public class RestoreGuiCommand extends Command { 9 | public RestoreGuiCommand() { 10 | super("restoregui", "Restore your saved GUI.", "No arguments, theres also a keybind for this, make sure you saved a gui first!",null); 11 | } 12 | 13 | @Override 14 | public int execute(String[] args, Logger logger, CommandEnvironment env) { 15 | if (args.length != 0) { 16 | logger.error("Invalid Arguments, usage: 'restoregui'."); 17 | return Commands.COMMAND_FAILURE; 18 | } 19 | 20 | if (SaveGuiCommand.savedScreen == null && SaveGuiCommand.savedScreenHandler == null) { 21 | logger.error("No GUI to restore."); 22 | return Commands.COMMAND_FAILURE; 23 | } 24 | 25 | client.setScreen(SaveGuiCommand.savedScreen); 26 | if (client.player != null) { 27 | client.player.currentScreenHandler = SaveGuiCommand.savedScreenHandler; 28 | } 29 | 30 | return Commands.COMMAND_SUCCESS; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/org/cmdutils/command/commands/SaveGuiCommand.java: -------------------------------------------------------------------------------- 1 | package org.cmdutils.command.commands; 2 | 3 | import net.minecraft.client.gui.screen.Screen; 4 | import net.minecraft.screen.ScreenHandler; 5 | import org.cmdutils.command.Command; 6 | import org.cmdutils.command.CommandEnvironment; 7 | import org.cmdutils.command.Commands; 8 | import org.cmdutils.terminal.gui.InGameTerminalGui; 9 | import org.cmdutils.terminal.logger.Logger; 10 | 11 | public class SaveGuiCommand extends Command { 12 | public static Screen savedScreen = null; 13 | public static ScreenHandler savedScreenHandler = null; 14 | 15 | public SaveGuiCommand() { 16 | super("savegui", "Saves your GUI so it can be restored.", "Use the restore gui command or keybind with this.",null); 17 | } 18 | 19 | @Override 20 | public int execute(String[] args, Logger logger, CommandEnvironment env) { 21 | if (args.length != 0) { 22 | logger.error("Invalid Arguments, usage: 'savegui'."); 23 | return Commands.COMMAND_FAILURE; 24 | } 25 | 26 | if (env == CommandEnvironment.IN_GAME && client.currentScreen instanceof InGameTerminalGui gui) { 27 | savedScreen = gui.previousScreen; 28 | savedScreenHandler = gui.previousScreenHandler; 29 | } 30 | 31 | if (env == CommandEnvironment.SWING) { 32 | savedScreen = client.currentScreen; 33 | if (client.player != null) { 34 | savedScreenHandler = client.player.currentScreenHandler; 35 | } 36 | } 37 | 38 | if (savedScreen == null && savedScreenHandler == null) { 39 | logger.error("No GUI to save."); 40 | return Commands.COMMAND_FAILURE; 41 | } 42 | 43 | logger.info("Saved GUI."); 44 | 45 | return Commands.COMMAND_SUCCESS; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/org/cmdutils/command/commands/SessionCommand.java: -------------------------------------------------------------------------------- 1 | package org.cmdutils.command.commands; 2 | 3 | import net.minecraft.client.session.Session; 4 | import org.cmdutils.MainClient; 5 | import org.cmdutils.command.Command; 6 | import org.cmdutils.command.CommandEnvironment; 7 | import org.cmdutils.command.Commands; 8 | import org.cmdutils.mixin.accessor.SessionAccessor; 9 | import org.cmdutils.terminal.logger.Logger; 10 | 11 | import java.util.UUID; 12 | 13 | public class SessionCommand extends Command { 14 | public SessionCommand() { 15 | // todo (mrbreak): rewrite this, its garbage 16 | super("session", "Session ID getter/setter.", "Okay I don't want to rant here, this is powerfull, but annoying to use, you will need to use this like 4 times to actually do anything. \n Syntax: \"session args0[get/set] IF SET args1[\"username\"/\"uuid\"/\"token\"/\"type\"] args2[value of previous switch argument, ex msa, \"MrBreakNFix\", etc]",null); 17 | } 18 | 19 | @Override 20 | public int execute(String[] args, Logger logger, CommandEnvironment env) { 21 | if (args.length < 1) { 22 | logger.error("Invalid Arguments."); 23 | return Commands.COMMAND_FAILURE; 24 | } 25 | 26 | if (args[0].equals("get")) { 27 | SessionAccessor session = ((SessionAccessor) client.getSession()); 28 | logger.info("Username: " + session.getUsername()); 29 | logger.info("UUID: " + session.getUuid().toString()); 30 | logger.info("Access Token: " + session.getAccessToken()); 31 | logger.info("Type: " + session.getAccountType().toString().toLowerCase()); 32 | return Commands.COMMAND_SUCCESS; 33 | } 34 | 35 | if (args[0].equals("set")) { 36 | if (args.length < 3) { 37 | logger.error("Not Enough Arguments."); 38 | return Commands.COMMAND_FAILURE; 39 | } 40 | 41 | if (args[1].equals("username")) { 42 | setUsername(args[2]); 43 | logger.info("Changed username."); 44 | return Commands.COMMAND_SUCCESS; 45 | } 46 | 47 | if (args[1].equals("uuid")) { 48 | if (!setUUID(args[2])) { 49 | logger.error("Invalid UUID."); 50 | return Commands.COMMAND_FAILURE; 51 | } 52 | logger.info("Changed UUID."); 53 | return Commands.COMMAND_SUCCESS; 54 | } 55 | 56 | if (args[1].equals("token")) { 57 | setAccessToken(args[2]); 58 | logger.info("Changed access token."); 59 | return Commands.COMMAND_SUCCESS; 60 | } 61 | 62 | if (args[1].equals("type")) { 63 | if (!setAccountType(args[2])) { 64 | logger.error("Invalid Account Type."); 65 | return Commands.COMMAND_FAILURE; 66 | } 67 | logger.info("Changed account type."); 68 | return Commands.COMMAND_SUCCESS; 69 | } 70 | 71 | logger.error("Invalid Session Field."); 72 | 73 | return Commands.COMMAND_FAILURE; 74 | } 75 | 76 | logger.error("Invalid Operation."); 77 | 78 | return Commands.COMMAND_FAILURE; 79 | } 80 | 81 | private static void setUsername(String username) { 82 | SessionAccessor session = ((SessionAccessor) Command.client.getSession()); 83 | session.setUsername(username); 84 | } 85 | 86 | private static boolean setUUID(String uuid) { 87 | SessionAccessor session = ((SessionAccessor) Command.client.getSession()); 88 | try { 89 | session.setUuid(UUID.fromString(uuid)); 90 | return true; 91 | } catch (Exception e) { 92 | MainClient.LOGGER.warn("Failed to set UUID, invalid UUID string input.", e); 93 | return false; 94 | } 95 | } 96 | 97 | private static void setAccessToken(String accessToken) { 98 | SessionAccessor session = ((SessionAccessor) Command.client.getSession()); 99 | session.setAccessToken(accessToken); 100 | } 101 | 102 | private static boolean setAccountType(String type) { 103 | Session.AccountType e = switch (type) { 104 | case "msa" -> Session.AccountType.MSA; 105 | case "mojang" -> Session.AccountType.MOJANG; 106 | case "legacy" -> Session.AccountType.LEGACY; 107 | default -> null; 108 | }; 109 | 110 | if (e == null) { 111 | return false; 112 | } 113 | 114 | SessionAccessor session = ((SessionAccessor) Command.client.getSession()); 115 | session.setAccountType(e); 116 | 117 | return true; 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/main/java/org/cmdutils/command/commands/SlashCommand.java: -------------------------------------------------------------------------------- 1 | package org.cmdutils.command.commands; 2 | 3 | import org.cmdutils.command.Command; 4 | import org.cmdutils.command.CommandEnvironment; 5 | import org.cmdutils.command.Commands; 6 | import org.cmdutils.terminal.logger.Logger; 7 | 8 | public class SlashCommand extends Command { 9 | public SlashCommand() { 10 | super("/", "Sends a command to the server: \"/ kill\" (with space)", "Syntax \"/ args0[command]\n Example: \"/ kill\" or \" / \"kill @e[type=item]\" \"",null); 11 | } 12 | 13 | @Override 14 | public int execute(String[] args, Logger logger, CommandEnvironment env) { 15 | if (client.getNetworkHandler() == null) { 16 | logger.error("You are not connected to a server."); 17 | return Commands.COMMAND_FAILURE; 18 | } 19 | 20 | if (args.length == 1) { 21 | client.getNetworkHandler().sendCommand(args[0]); 22 | logger.info("Sent command."); 23 | return Commands.COMMAND_SUCCESS; 24 | } 25 | 26 | logger.error("Invalid Arguments."); 27 | 28 | return Commands.COMMAND_FAILURE; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/org/cmdutils/command/commands/SwingCommand.java: -------------------------------------------------------------------------------- 1 | package org.cmdutils.command.commands; 2 | 3 | import org.cmdutils.MainClient; 4 | import org.cmdutils.command.Command; 5 | import org.cmdutils.command.CommandEnvironment; 6 | import org.cmdutils.command.Commands; 7 | import org.cmdutils.terminal.gui.TerminalGui; 8 | import org.cmdutils.terminal.logger.Logger; 9 | 10 | public class SwingCommand extends Command { 11 | public SwingCommand() { 12 | super("swing", "Open the CMD-Utils (Swing) terminal.", "Telnet is better, open up a (real) terminal and run \"telnet localhost 3300\"",null); 13 | } 14 | 15 | @Override 16 | public int execute(String[] args, Logger logger, CommandEnvironment env) { 17 | if (args.length != 0) { 18 | logger.error("Invalid Arguments, usage: 'swing'."); 19 | return Commands.COMMAND_FAILURE; 20 | } 21 | 22 | try { 23 | new TerminalGui().show(); 24 | logger.info("Opened new CMD-Utils (Swing) terminal."); 25 | 26 | return Commands.COMMAND_SUCCESS; 27 | } catch (Exception e) { 28 | MainClient.LOGGER.error("Failed to open CMD-Utils (Swing) terminal.", e); 29 | logger.error("Failed to open CMD-Utils (Swing) terminal", e); 30 | 31 | return Commands.COMMAND_FAILURE; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/org/cmdutils/command/commands/TradeCommand.java: -------------------------------------------------------------------------------- 1 | package org.cmdutils.command.commands; 2 | 3 | import net.minecraft.network.packet.c2s.play.SelectMerchantTradeC2SPacket; 4 | import org.cmdutils.command.Command; 5 | import org.cmdutils.command.CommandEnvironment; 6 | import org.cmdutils.command.Commands; 7 | import org.cmdutils.terminal.logger.Logger; 8 | import org.cmdutils.util.Utils; 9 | 10 | public class TradeCommand extends Command { 11 | public TradeCommand() { 12 | super("trade", "Select villager trade by ID, via SelectMerchantTrade packet.", "Syntax: \"trade args0[tradeId (int)]\"\n ",null); 13 | } 14 | 15 | @Override 16 | public int execute(String[] args, Logger logger, CommandEnvironment env) { 17 | if (args.length != 1) { 18 | logger.error("Invalid Arguments."); 19 | return Commands.COMMAND_FAILURE; 20 | } 21 | 22 | if (client.getNetworkHandler() == null) { 23 | logger.error("You are not connected to a server."); 24 | return Commands.COMMAND_FAILURE; 25 | } 26 | 27 | Integer tradeId = Utils.toInteger(args[0]); 28 | 29 | if (tradeId == null) { 30 | logger.error("Invalid Trade ID."); 31 | return Commands.COMMAND_FAILURE; 32 | } 33 | 34 | client.getNetworkHandler().sendPacket(new SelectMerchantTradeC2SPacket(tradeId)); 35 | logger.info("Sent SelectMerchantTrade packet."); 36 | 37 | return Commands.COMMAND_SUCCESS; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/org/cmdutils/command/commands/WakeCommand.java: -------------------------------------------------------------------------------- 1 | package org.cmdutils.command.commands; 2 | 3 | import org.cmdutils.command.Command; 4 | import org.cmdutils.command.CommandEnvironment; 5 | import org.cmdutils.command.Commands; 6 | import org.cmdutils.terminal.logger.Logger; 7 | 8 | public class WakeCommand extends Command { 9 | public WakeCommand() { 10 | super("wake", "Wake up from a bed client-side.", "Im waking up, I feel it in my bones, enough to make my system blow... But seriously, no arguments",null); 11 | } 12 | 13 | @Override 14 | public int execute(String[] args, Logger logger, CommandEnvironment env) { 15 | if (args.length != 0) { 16 | logger.error("Invalid Arguments, usage: 'wake'."); 17 | return Commands.COMMAND_FAILURE; 18 | } 19 | 20 | if (client.player == null) { 21 | logger.error("You are not connected to a server."); 22 | return Commands.COMMAND_FAILURE; 23 | } 24 | 25 | if (client.player.isSleeping()) { 26 | client.player.wakeUp(); 27 | logger.info("Woke up player (client-side.)"); 28 | } else { 29 | logger.error("You are not sleeping."); 30 | return Commands.COMMAND_FAILURE; 31 | } 32 | 33 | return Commands.COMMAND_SUCCESS; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/org/cmdutils/mixin/ClientConnectionMixin.java: -------------------------------------------------------------------------------- 1 | package org.cmdutils.mixin; 2 | 3 | import net.minecraft.network.ClientConnection; 4 | import net.minecraft.network.packet.Packet; 5 | import org.cmdutils.util.ClassMap; 6 | import org.cmdutils.util.Mcfw; 7 | import org.cmdutils.util.McfwFilterType; 8 | import org.spongepowered.asm.mixin.Mixin; 9 | import org.spongepowered.asm.mixin.injection.At; 10 | import org.spongepowered.asm.mixin.injection.Inject; 11 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 12 | 13 | @Mixin(ClientConnection.class) 14 | public class ClientConnectionMixin { 15 | @Inject(at = @At("HEAD"), method = "send(Lnet/minecraft/network/packet/Packet;)V", cancellable = true) 16 | public void send(Packet packet, CallbackInfo ci) { 17 | if (Mcfw.enabled) { 18 | String name = ClassMap.getMappedName(packet.getClass()); 19 | McfwFilterType type = Mcfw.filteredPackets.get(name); 20 | if (type == null) { 21 | type = Mcfw.filteredPackets.get("all"); 22 | } 23 | if (type != null) { 24 | if (type == McfwFilterType.DELAYED) { 25 | Mcfw.delayedPackets.add(packet); 26 | } 27 | ci.cancel(); 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/cmdutils/mixin/ScreenMixin.java: -------------------------------------------------------------------------------- 1 | package org.cmdutils.mixin; 2 | 3 | import net.minecraft.client.MinecraftClient; 4 | import net.minecraft.client.gui.screen.Screen; 5 | import org.cmdutils.MainClient; 6 | import org.cmdutils.terminal.gui.InGameTerminalGui; 7 | import org.jetbrains.annotations.Nullable; 8 | import org.spongepowered.asm.mixin.Mixin; 9 | import org.spongepowered.asm.mixin.Shadow; 10 | import org.spongepowered.asm.mixin.injection.At; 11 | import org.spongepowered.asm.mixin.injection.Inject; 12 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; 13 | 14 | @Mixin(Screen.class) 15 | public abstract class ScreenMixin { 16 | @Shadow 17 | public static boolean hasControlDown() { 18 | return false; 19 | } 20 | 21 | @Shadow 22 | @Nullable 23 | protected MinecraftClient client; 24 | 25 | @Inject(at = @At("TAIL"), method = "keyPressed") 26 | public void keyPressed(int keyCode, int scanCode, int modifiers, CallbackInfoReturnable cir) { 27 | if (hasControlDown() && keyCode == MainClient.terminalKey.boundKey.getCode()) { 28 | if (this.client != null && !(this.client.currentScreen instanceof InGameTerminalGui)) { 29 | this.client.setScreen(new InGameTerminalGui(this.client.currentScreen, this.client.player == null ? null : this.client.player.currentScreenHandler)); 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/org/cmdutils/mixin/accessor/SessionAccessor.java: -------------------------------------------------------------------------------- 1 | package org.cmdutils.mixin.accessor; 2 | 3 | import net.minecraft.client.session.Session; 4 | import org.spongepowered.asm.mixin.Mixin; 5 | import org.spongepowered.asm.mixin.Mutable; 6 | import org.spongepowered.asm.mixin.gen.Accessor; 7 | 8 | import java.util.UUID; 9 | 10 | @Mixin(Session.class) 11 | public interface SessionAccessor { 12 | @Accessor 13 | String getUsername(); 14 | 15 | @Accessor 16 | UUID getUuid(); 17 | 18 | @Accessor 19 | String getAccessToken(); 20 | 21 | @Accessor 22 | Session.AccountType getAccountType(); 23 | 24 | @Accessor 25 | @Mutable 26 | void setUsername(String username); 27 | 28 | @Accessor 29 | @Mutable 30 | void setUuid(UUID uuid); 31 | 32 | @Accessor 33 | @Mutable 34 | void setAccessToken(String accessToken); 35 | 36 | @Accessor 37 | @Mutable 38 | void setAccountType(Session.AccountType accountType); 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/org/cmdutils/terminal/gui/InGameTerminalGui.java: -------------------------------------------------------------------------------- 1 | package org.cmdutils.terminal.gui; 2 | 3 | import net.minecraft.client.gui.DrawContext; 4 | import net.minecraft.client.gui.screen.Screen; 5 | import net.minecraft.client.gui.widget.EditBoxWidget; 6 | import net.minecraft.client.gui.widget.TextFieldWidget; 7 | import net.minecraft.screen.ScreenHandler; 8 | import net.minecraft.text.Text; 9 | import org.cmdutils.MainClient; 10 | import org.cmdutils.command.CommandEnvironment; 11 | import org.cmdutils.command.CommandParser; 12 | import org.cmdutils.command.RunnableCommand; 13 | import org.cmdutils.terminal.logger.InGameLogger; 14 | import org.lwjgl.glfw.GLFW; 15 | 16 | import java.util.ArrayList; 17 | import java.util.List; 18 | 19 | public class InGameTerminalGui extends Screen { 20 | public EditBoxWidget log; 21 | public InGameLogger logger; 22 | 23 | public TextFieldWidget prompt; 24 | 25 | public final Screen previousScreen; 26 | public final ScreenHandler previousScreenHandler; 27 | 28 | private final List queuedCommands = new ArrayList<>(); 29 | 30 | private final List commandHistory = new ArrayList<>(); 31 | private int historyIndex = -1; 32 | 33 | private final Text logText = Text.of(""); 34 | private final Text promptText = Text.of(""); 35 | 36 | public InGameTerminalGui(Screen previousScreen, ScreenHandler previousScreenHandler) { 37 | super(Text.of("CMD-Utils Terminal")); 38 | 39 | this.previousScreen = previousScreen; 40 | this.previousScreenHandler = previousScreenHandler; 41 | } 42 | 43 | @Override 44 | public void init() { 45 | this.log = new EditBoxWidget( 46 | this.textRenderer, 47 | (this.width / 2) - this.width / 4, 48 | this.height / 4, 49 | this.width / 2, 50 | this.height / 3, 51 | Text.of(""), 52 | this.logText 53 | ) { 54 | @Override 55 | public boolean charTyped(char chr, int modifiers) { 56 | return false; 57 | } 58 | }; 59 | 60 | this.logger = new InGameLogger(this.log); 61 | 62 | this.prompt = new TextFieldWidget( 63 | this.textRenderer, 64 | (this.width / 2) - this.width / 4, 65 | (this.height / 3) + this.height / 4 + 10, 66 | this.width / 2, 67 | 20, 68 | this.promptText 69 | ) { 70 | @Override 71 | public boolean keyPressed(int keyCode, int scanCode, int modifiers) { 72 | if (keyCode == GLFW.GLFW_KEY_ENTER && (!this.getText().isEmpty() || !InGameTerminalGui.this.queuedCommands.isEmpty())) { 73 | RunnableCommand command = CommandParser.parseCommand(this.getText(), InGameTerminalGui.this.logger, CommandEnvironment.IN_GAME); 74 | if (!this.getText().isEmpty() && (InGameTerminalGui.this.commandHistory.isEmpty() || !InGameTerminalGui.this.commandHistory.get(InGameTerminalGui.this.commandHistory.size() - 1).equals(this.getText()))) { 75 | InGameTerminalGui.this.commandHistory.add(this.getText()); 76 | } 77 | 78 | InGameTerminalGui.this.historyIndex = InGameTerminalGui.this.commandHistory.size(); 79 | 80 | if (!this.getText().isEmpty()) { 81 | InGameTerminalGui.this.queuedCommands.add(command); 82 | } 83 | this.setText(""); 84 | 85 | if (hasControlDown()) { 86 | return false; 87 | } 88 | 89 | for (RunnableCommand c : InGameTerminalGui.this.queuedCommands) { 90 | if (c == null) { 91 | InGameTerminalGui.this.logger.error("Invalid Command."); 92 | } else { 93 | try { 94 | c.execute(); 95 | } catch (Exception ex) { 96 | MainClient.LOGGER.error("Exception thrown while executing CMD-Utils command.", ex); 97 | } 98 | } 99 | } 100 | 101 | InGameTerminalGui.this.queuedCommands.clear(); 102 | 103 | return false; 104 | } 105 | 106 | return super.keyPressed(keyCode, scanCode, modifiers); 107 | } 108 | }; 109 | this.prompt.setMaxLength(4096); 110 | 111 | this.addDrawableChild(this.log); 112 | this.addDrawableChild(this.prompt); 113 | 114 | this.setInitialFocus(this.prompt); 115 | } 116 | 117 | @Override 118 | public boolean keyPressed(int keyCode, int scanCode, int modifiers) { 119 | if (this.prompt.isFocused()) { 120 | if (keyCode == GLFW.GLFW_KEY_UP && InGameTerminalGui.this.historyIndex > 0) { 121 | this.prompt.setText(InGameTerminalGui.this.commandHistory.get(--InGameTerminalGui.this.historyIndex)); 122 | } 123 | 124 | if (keyCode == GLFW.GLFW_KEY_DOWN && InGameTerminalGui.this.historyIndex < InGameTerminalGui.this.commandHistory.size() - 1) { 125 | this.prompt.setText(InGameTerminalGui.this.commandHistory.get(++InGameTerminalGui.this.historyIndex)); 126 | } 127 | 128 | if (keyCode == GLFW.GLFW_KEY_UP || keyCode == GLFW.GLFW_KEY_DOWN) { 129 | return false; 130 | } 131 | } 132 | 133 | return super.keyPressed(keyCode, scanCode, modifiers); 134 | } 135 | 136 | @Override 137 | public void render(DrawContext context, int mouseX, int mouseY, float delta) { 138 | super.renderBackground(context, mouseX, mouseY, delta); 139 | super.render(context, mouseX, mouseY, delta); 140 | 141 | context.drawCenteredTextWithShadow(this.textRenderer, "CMD-Utils Terminal", this.width / 2, this.height / 4 - 20, 0xFFFFFF); 142 | } 143 | 144 | @Override 145 | public void close() { 146 | if (this.client != null) { 147 | this.client.setScreen(this.previousScreen); 148 | if (this.client.player != null) { 149 | this.client.player.currentScreenHandler = this.previousScreenHandler; 150 | } 151 | } 152 | } 153 | 154 | @Override 155 | public boolean shouldPause() { 156 | return false; 157 | } 158 | 159 | @Override 160 | public boolean shouldCloseOnEsc() { 161 | return true; 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /src/main/java/org/cmdutils/terminal/gui/TerminalGui.java: -------------------------------------------------------------------------------- 1 | package org.cmdutils.terminal.gui; 2 | 3 | import net.minecraft.client.MinecraftClient; 4 | import org.cmdutils.MainClient; 5 | import org.cmdutils.command.CommandEnvironment; 6 | import org.cmdutils.command.CommandParser; 7 | import org.cmdutils.command.RunnableCommand; 8 | import org.cmdutils.terminal.logger.TextAreaLogger; 9 | import org.cmdutils.util.FontUtil; 10 | 11 | import javax.swing.*; 12 | import java.awt.*; 13 | import java.awt.event.ComponentEvent; 14 | import java.awt.event.ComponentListener; 15 | import java.awt.event.KeyEvent; 16 | import java.awt.event.KeyListener; 17 | import java.util.ArrayList; 18 | import java.util.List; 19 | 20 | public class TerminalGui { 21 | public JFrame frame; 22 | 23 | public JTextArea logArea; 24 | public JScrollPane logScroll; 25 | public JTextField promptField; 26 | 27 | public TextAreaLogger logger; 28 | 29 | private final List queuedCommands = new ArrayList<>(); 30 | 31 | private final List commandHistory = new ArrayList<>(); 32 | private int historyIndex = -1; 33 | 34 | public TerminalGui() { 35 | this.init(); 36 | } 37 | 38 | private void init() { 39 | this.frame = new JFrame("CMD-Utils Terminal"); 40 | this.frame.setBounds(0, 0, 600, 475); 41 | this.frame.setMinimumSize(new Dimension(300, 190)); 42 | this.frame.setLocationRelativeTo(null); 43 | this.frame.setLayout(null); 44 | this.frame.addComponentListener(new ComponentListener() { 45 | @Override 46 | public void componentResized(ComponentEvent e) { 47 | TerminalGui.this.update(); 48 | } 49 | 50 | @Override 51 | public void componentMoved(ComponentEvent e) { 52 | } 53 | 54 | @Override 55 | public void componentShown(ComponentEvent e) { 56 | } 57 | 58 | @Override 59 | public void componentHidden(ComponentEvent e) { 60 | } 61 | }); 62 | 63 | Image icon = Toolkit.getDefaultToolkit().getImage(TerminalGui.class.getClassLoader().getResource("assets/cmd-utils/icon.png")); 64 | if (icon == null) { 65 | MainClient.LOGGER.warn("Failed to load icon for CMD-Utils terminal GUI (assets/cmd-utils/icon.png)"); 66 | } else { 67 | this.frame.setIconImage(icon); 68 | } 69 | 70 | this.logArea = new JTextArea(); 71 | this.logArea.setForeground(Color.WHITE); 72 | this.logArea.setBackground(Color.BLACK); 73 | this.logArea.setBorder(BorderFactory.createEmptyBorder()); 74 | this.logArea.setFont(FontUtil.AWT_MONOSPACE); 75 | this.logArea.setLineWrap(true); 76 | this.logArea.setEditable(false); 77 | this.logArea.setFocusable(false); 78 | 79 | this.logScroll = new JScrollPane(this.logArea); 80 | this.logScroll.setBackground(Color.BLACK); 81 | this.logScroll.setBorder(BorderFactory.createEmptyBorder()); 82 | this.logScroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); 83 | this.logScroll.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); 84 | 85 | this.logger = new TextAreaLogger(this.logArea); 86 | 87 | this.promptField = new JTextField(); 88 | this.promptField.setForeground(Color.WHITE); 89 | this.promptField.setBackground(Color.BLACK); 90 | this.promptField.setCaretColor(Color.WHITE); 91 | this.promptField.setBorder(BorderFactory.createEmptyBorder()); 92 | this.promptField.setFont(FontUtil.AWT_MONOSPACE); 93 | this.promptField.setEditable(true); 94 | this.promptField.addKeyListener(new KeyListener() { 95 | @Override 96 | public void keyPressed(KeyEvent e) { 97 | if (e.getKeyCode() == KeyEvent.VK_ENTER && (!TerminalGui.this.promptField.getText().isEmpty() || !TerminalGui.this.queuedCommands.isEmpty())) { 98 | RunnableCommand command = CommandParser.parseCommand(TerminalGui.this.promptField.getText(), TerminalGui.this.logger, CommandEnvironment.SWING); 99 | if (!TerminalGui.this.promptField.getText().isEmpty() && (TerminalGui.this.commandHistory.isEmpty() || !TerminalGui.this.commandHistory.get(TerminalGui.this.commandHistory.size() - 1).equals(TerminalGui.this.promptField.getText()))) { 100 | TerminalGui.this.commandHistory.add(TerminalGui.this.promptField.getText()); 101 | } 102 | 103 | TerminalGui.this.historyIndex = TerminalGui.this.commandHistory.size(); 104 | 105 | if (!TerminalGui.this.promptField.getText().isEmpty()) { 106 | TerminalGui.this.queuedCommands.add(command); 107 | } 108 | TerminalGui.this.promptField.setText(""); 109 | 110 | if (e.isControlDown()) { 111 | return; 112 | } 113 | 114 | for (RunnableCommand c : TerminalGui.this.queuedCommands) { 115 | if (c == null) { 116 | TerminalGui.this.logger.error("Invalid Command."); 117 | } else { 118 | MinecraftClient.getInstance().send(() -> { 119 | try { 120 | c.execute(); 121 | } catch (Exception ex) { 122 | MainClient.LOGGER.error("Exception thrown while executing CMD-Utils command.", ex); 123 | } 124 | }); 125 | } 126 | } 127 | 128 | TerminalGui.this.queuedCommands.clear(); 129 | } 130 | 131 | if (e.getKeyCode() == KeyEvent.VK_UP && TerminalGui.this.historyIndex > 0) { 132 | TerminalGui.this.promptField.setText(TerminalGui.this.commandHistory.get(--TerminalGui.this.historyIndex)); 133 | } 134 | 135 | if (e.getKeyCode() == KeyEvent.VK_DOWN && TerminalGui.this.historyIndex < TerminalGui.this.commandHistory.size() - 1) { 136 | TerminalGui.this.promptField.setText(TerminalGui.this.commandHistory.get(++TerminalGui.this.historyIndex)); 137 | } 138 | } 139 | 140 | @Override 141 | public void keyReleased(KeyEvent e) { 142 | } 143 | 144 | @Override 145 | public void keyTyped(KeyEvent e) { 146 | } 147 | }); 148 | 149 | this.frame.add(this.logScroll); 150 | this.frame.add(this.promptField); 151 | } 152 | 153 | private void update() { 154 | this.logScroll.setBounds(0, 0, this.frame.getWidth(), this.frame.getHeight() - 50); 155 | this.promptField.setBounds(0, this.frame.getHeight() - 50, this.frame.getWidth(), 20); 156 | } 157 | 158 | public void show() { 159 | this.frame.setVisible(true); 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /src/main/java/org/cmdutils/terminal/logger/InGameLogger.java: -------------------------------------------------------------------------------- 1 | package org.cmdutils.terminal.logger; 2 | 3 | import net.minecraft.client.gui.widget.EditBoxWidget; 4 | 5 | public class InGameLogger implements Logger { 6 | public EditBoxWidget log; 7 | 8 | public InGameLogger(EditBoxWidget log) { 9 | this.log = log; 10 | } 11 | 12 | @Override 13 | public boolean canClear() { 14 | return true; 15 | } 16 | 17 | @Override 18 | public void clear() { 19 | this.log.setText(""); 20 | } 21 | 22 | @Override 23 | public void print(String text) { 24 | this.log.setText(this.log.getText() + text); 25 | } 26 | 27 | @Override 28 | public void println(String text) { 29 | this.print(text + '\n'); 30 | } 31 | 32 | @Override 33 | public void info(String log) { 34 | this.println("I: " + log); 35 | } 36 | 37 | @Override 38 | public void warn(String log) { 39 | this.println("W: " + log); 40 | } 41 | 42 | @Override 43 | public void error(String log) { 44 | this.println("E: " + log); 45 | } 46 | 47 | @Override 48 | public void error(Throwable throwable) { 49 | this.error(throwable.toString()); 50 | } 51 | 52 | @Override 53 | public void error(String log, Throwable throwable) { 54 | this.error(log + " : " + throwable.toString()); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/org/cmdutils/terminal/logger/Logger.java: -------------------------------------------------------------------------------- 1 | package org.cmdutils.terminal.logger; 2 | 3 | public interface Logger { 4 | boolean canClear(); 5 | void clear(); 6 | void print(String text); 7 | void println(String text); 8 | void info(String log); 9 | void warn(String log); 10 | void error(String log); 11 | void error(Throwable throwable); 12 | void error(String log, Throwable throwable); 13 | } -------------------------------------------------------------------------------- /src/main/java/org/cmdutils/terminal/logger/NullLogger.java: -------------------------------------------------------------------------------- 1 | package org.cmdutils.terminal.logger; 2 | 3 | public class NullLogger implements Logger { 4 | 5 | @Override 6 | public boolean canClear() { 7 | return false; 8 | } 9 | 10 | @Override 11 | public void clear() { 12 | } 13 | 14 | @Override 15 | public void print(String text) { 16 | } 17 | 18 | @Override 19 | public void println(String text) { 20 | } 21 | 22 | @Override 23 | public void info(String log) { 24 | } 25 | 26 | @Override 27 | public void warn(String log) { 28 | } 29 | 30 | @Override 31 | public void error(String log) { 32 | } 33 | 34 | @Override 35 | public void error(Throwable throwable) { 36 | } 37 | 38 | @Override 39 | public void error(String log, Throwable throwable) { 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/org/cmdutils/terminal/logger/TelnetLogger.java: -------------------------------------------------------------------------------- 1 | package org.cmdutils.terminal.logger; 2 | 3 | import org.cmdutils.terminal.telnet.TelnetTerminal; 4 | 5 | import java.util.List; 6 | 7 | public class TelnetLogger implements Logger { 8 | private List sessions; 9 | 10 | public TelnetLogger(List sessions) { 11 | this.sessions = sessions; 12 | } 13 | 14 | @Override 15 | public boolean canClear() { 16 | return true; 17 | } 18 | 19 | @Override 20 | public void clear() { 21 | for (TelnetTerminal.TelnetSession session : sessions) { 22 | session.printOut("\u001B[2J"); 23 | } 24 | } 25 | 26 | @Override 27 | public void print(String text) { 28 | for (TelnetTerminal.TelnetSession session : sessions) { 29 | session.printOut(text); 30 | } 31 | System.out.print(text); 32 | } 33 | 34 | @Override 35 | public void println(String text) { 36 | for (TelnetTerminal.TelnetSession session : sessions) { 37 | session.printOut(text); 38 | } 39 | System.out.print(text); 40 | } 41 | 42 | @Override 43 | public void info(String log) { 44 | String infoPrefix = TelnetTerminal.yellow + "(I) " + TelnetTerminal.reset; 45 | for (TelnetTerminal.TelnetSession session : sessions) { 46 | session.printOut(infoPrefix + log); 47 | } 48 | System.out.print(log); 49 | 50 | } 51 | 52 | @Override 53 | public void warn(String log) { 54 | String warnPrefix = TelnetTerminal.brightYellow + "(W) " + TelnetTerminal.reset; 55 | for (TelnetTerminal.TelnetSession session : sessions) { 56 | session.printOut(warnPrefix + log); 57 | } 58 | System.out.print(log); 59 | 60 | } 61 | 62 | @Override 63 | public void error(String log) { 64 | String errorPrefix = TelnetTerminal.red + "(E) " + TelnetTerminal.reset; 65 | for (TelnetTerminal.TelnetSession session : sessions) { 66 | session.printOut(errorPrefix + log); 67 | } 68 | System.out.print(log); 69 | 70 | } 71 | 72 | @Override 73 | public void error(Throwable throwable) { 74 | error(throwable.toString()); 75 | } 76 | 77 | @Override 78 | public void error(String log, Throwable throwable) { 79 | error(log + " : " + throwable.toString()); 80 | } 81 | } -------------------------------------------------------------------------------- /src/main/java/org/cmdutils/terminal/logger/TextAreaLogger.java: -------------------------------------------------------------------------------- 1 | package org.cmdutils.terminal.logger; 2 | 3 | import javax.swing.*; 4 | 5 | public class TextAreaLogger implements Logger { 6 | public JTextArea area; 7 | 8 | public TextAreaLogger(JTextArea area) { 9 | this.area = area; 10 | } 11 | 12 | @Override 13 | public boolean canClear() { 14 | return true; 15 | } 16 | 17 | @Override 18 | public void clear() { 19 | this.area.setText(""); 20 | } 21 | 22 | @Override 23 | public void print(String text) { 24 | this.area.setText(this.area.getText() + text); 25 | } 26 | 27 | @Override 28 | public void println(String text) { 29 | this.print(text + '\n'); 30 | } 31 | 32 | @Override 33 | public void info(String log) { 34 | this.println("I: " + log); 35 | } 36 | 37 | @Override 38 | public void warn(String log) { 39 | this.println("W: " + log); 40 | } 41 | 42 | @Override 43 | public void error(String log) { 44 | this.println("E: " + log); 45 | } 46 | 47 | @Override 48 | public void error(Throwable throwable) { 49 | this.error(throwable.toString()); 50 | } 51 | 52 | @Override 53 | public void error(String log, Throwable throwable) { 54 | this.error(log + " : " + throwable.toString()); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/org/cmdutils/terminal/telnet/TelnetTerminal.java: -------------------------------------------------------------------------------- 1 | package org.cmdutils.terminal.telnet; 2 | 3 | import org.cmdutils.MainClient; 4 | import org.cmdutils.command.*; 5 | import org.cmdutils.terminal.logger.TelnetLogger; 6 | 7 | import java.io.BufferedReader; 8 | import java.io.IOException; 9 | import java.io.InputStreamReader; 10 | import java.io.PrintWriter; 11 | import java.net.ServerSocket; 12 | import java.net.Socket; 13 | import java.util.ArrayList; 14 | import java.util.Collections; 15 | import java.util.List; 16 | 17 | public class TelnetTerminal { 18 | private List sessions = Collections.synchronizedList(new ArrayList<>()); 19 | public TelnetLogger logger; 20 | 21 | public static String reset = "\u001B[0m"; 22 | public static String black = "\u001B[30m"; 23 | public static String red = "\u001B[31m"; 24 | public static String green = "\u001B[32m"; 25 | public static String yellow = "\u001B[33m"; 26 | public static String blue = "\u001B[34m"; 27 | public static String purple = "\u001B[35m"; 28 | public static String cyan = "\u001B[36m"; 29 | public static String white = "\u001B[37m"; 30 | public static String gray = "\u001B[90m"; 31 | public static String brightRed = "\u001B[91m"; 32 | public static String brightGreen = "\u001B[92m"; 33 | public static String brightYellow = "\u001B[93m"; 34 | public static String brightBlue = "\u001B[94m"; 35 | public static String brightPurple = "\u001B[95m"; 36 | public static String brightCyan = "\u001B[96m"; 37 | public static String brightWhite = "\u001B[97m"; 38 | private final List queuedCommands = new ArrayList<>(); 39 | 40 | public class TelnetSession implements Runnable { 41 | private Socket socket; 42 | private BufferedReader in; 43 | private PrintWriter out; 44 | 45 | public TelnetSession(Socket socket) throws IOException { 46 | this.socket = socket; 47 | this.in = new BufferedReader(new InputStreamReader(socket.getInputStream())); 48 | this.out = new PrintWriter(socket.getOutputStream(), true); 49 | } 50 | 51 | public void open() throws IOException { 52 | printOut("\n\n\n ╔═════════════════════════════════════╗"); 53 | printOut(" ║ " + green + "Connected to CMD-Utils via telnet" + reset + " ║"); 54 | printOut(" ╚═════════════════════════════════════╝\n\n"); 55 | printPrompt(); 56 | TelnetTerminal.this.logger = new TelnetLogger(new ArrayList<>(sessions)); 57 | } 58 | 59 | public void close() throws IOException { 60 | printOut("Session closed"); 61 | socket.close(); 62 | } 63 | 64 | public void handleCommand(String command) { 65 | 66 | 67 | RunnableCommand cmd = CommandParser.parseCommand(command, TelnetTerminal.this.logger, CommandEnvironment.TELNET); 68 | TelnetTerminal.this.queuedCommands.add(cmd); 69 | 70 | if (command.equals("exit") || (command.equals("^C"))) { 71 | TelnetTerminal.this.logger.info("Press ^], then ^D to exit a telnet session"); 72 | return; 73 | } 74 | 75 | for (RunnableCommand c : queuedCommands) { 76 | if (c == null) { 77 | TelnetTerminal.this.logger.error("Invalid Command: " + command); 78 | 79 | String guessedCommand = guessCommand(command); 80 | if (guessedCommand != null && !guessedCommand.isEmpty()) { 81 | TelnetTerminal.this.logger.error("Did you mean: " + brightYellow + guessedCommand + "?"); 82 | } else { 83 | TelnetTerminal.this.logger.error("Did you mean: " + brightYellow + "$ " +command + reset + "?"); 84 | } 85 | 86 | } else { 87 | try { 88 | c.execute(); 89 | } catch (Exception ex) { 90 | MainClient.LOGGER.error("Exception thrown while executing CMD-Utils command.", ex); 91 | } 92 | } 93 | } 94 | queuedCommands.clear(); 95 | printPrompt(); 96 | } 97 | 98 | 99 | public void printOut(String text) { 100 | out.println(text); 101 | MainClient.LOGGER.info("TELNET: " + text); 102 | } 103 | 104 | public void printPrompt() { 105 | out.print(brightCyan + "cmd-utils > " + reset); 106 | out.flush(); 107 | } 108 | 109 | public void readAndHandleCommand() { 110 | try { 111 | String command = in.readLine(); 112 | if (command != null) { 113 | handleCommand(command); 114 | } 115 | } catch (IOException e) { 116 | e.printStackTrace(); 117 | } 118 | } 119 | 120 | @Override 121 | public void run() { 122 | try { 123 | open(); 124 | while (!socket.isClosed()) { 125 | readAndHandleCommand(); 126 | } 127 | } catch (IOException e) { 128 | e.printStackTrace(); 129 | } finally { 130 | try { 131 | close(); 132 | } catch (IOException e) { 133 | e.printStackTrace(); 134 | } 135 | } 136 | } 137 | 138 | 139 | public String guessCommand(String inputCommand) { 140 | List availableCommands = getAvailableCommands(); 141 | String guessedCommand = ""; 142 | int maxMatches = 0; 143 | 144 | for (String command : availableCommands) { 145 | int matches = 0; 146 | int minLength = Math.min(inputCommand.length(), command.length()); 147 | 148 | // Check for partial matches 149 | for (int i = 0; i < minLength; i++) { 150 | if (inputCommand.charAt(i) == command.charAt(i)) { 151 | matches++; 152 | } else { 153 | break; 154 | } 155 | } 156 | 157 | // Update guessedCommand if the current command has more matches 158 | if (matches > maxMatches || (matches == maxMatches && command.length() < guessedCommand.length())) { 159 | maxMatches = matches; 160 | guessedCommand = command; 161 | } 162 | } 163 | 164 | return guessedCommand; 165 | } 166 | 167 | private List getAvailableCommands() { 168 | List availableCommands = new ArrayList<>(); 169 | for (Command command : Commands.COMMANDS) { 170 | availableCommands.add(command.getName()); 171 | } 172 | return availableCommands; 173 | } 174 | } 175 | 176 | public void handleConnections(int port) throws IOException { 177 | ServerSocket serverSocket = new ServerSocket(port); 178 | while (true) { 179 | try { 180 | Socket clientSocket = serverSocket.accept(); 181 | TelnetSession session = new TelnetSession(clientSocket); 182 | sessions.add(session); 183 | Thread sessionThread = new Thread(session); 184 | sessionThread 185 | 186 | .start(); 187 | } catch (IOException e) { 188 | e.printStackTrace(); 189 | } 190 | } 191 | } 192 | } -------------------------------------------------------------------------------- /src/main/java/org/cmdutils/util/ClassMap.java: -------------------------------------------------------------------------------- 1 | package org.cmdutils.util; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | import java.util.regex.Pattern; 6 | 7 | public class ClassMap { 8 | public static final Map PACKET_MAP = new HashMap<>(); 9 | 10 | public static String formatClassName(String name) { 11 | String[] parts = name.isEmpty() ? new String[]{name} : name.split(Pattern.quote(".")); 12 | return parts[parts.length - 1]; 13 | } 14 | 15 | public static String getMappedName(Class clazz) { 16 | String className = formatClassName(clazz.getName()); 17 | String packetName = PACKET_MAP.get(className); 18 | return packetName == null ? className.replace("C2SPacket", "") : packetName; 19 | } 20 | 21 | static { 22 | PACKET_MAP.put("class_2793", "TeleportConfirm"); 23 | PACKET_MAP.put("class_2795", "QueryBlockNbt"); 24 | PACKET_MAP.put("class_2797", "ChatMessage"); 25 | PACKET_MAP.put("class_2799", "ClientStatus"); 26 | PACKET_MAP.put("class_2803", "ClientOptions"); 27 | PACKET_MAP.put("class_2805", "RequestCommandCompletions"); 28 | PACKET_MAP.put("class_2811", "ButtonClick"); 29 | PACKET_MAP.put("class_2813", "ClickSlot"); 30 | PACKET_MAP.put("class_2815", "CloseHandledScreen"); 31 | PACKET_MAP.put("class_2817", "CustomPayload"); 32 | PACKET_MAP.put("class_2820", "BookUpdate"); 33 | PACKET_MAP.put("class_2822", "QueryEntityNbt"); 34 | PACKET_MAP.put("class_2824", "PlayerInteractEntity"); 35 | PACKET_MAP.put("class_2824$class_5909", "PlayerInteractEntity$InteractHandler"); 36 | PACKET_MAP.put("class_2824$class_5910", "PlayerInteractEntity$InteractAtHandler"); 37 | PACKET_MAP.put("class_2827", "KeepAlive"); 38 | PACKET_MAP.put("class_2828$class_2829", "PlayerMove$PositionAndOnGround"); 39 | PACKET_MAP.put("class_2828$class_2830", "PlayerMove$Full"); 40 | PACKET_MAP.put("class_2828$class_2831", "PlayerMove$LookAndOnGround"); 41 | PACKET_MAP.put("class_2828$class_5911", "PlayerMove$OnGroundOnly"); 42 | PACKET_MAP.put("class_2833", "VehicleMove"); 43 | PACKET_MAP.put("class_2836", "BoatPaddleState"); 44 | PACKET_MAP.put("class_2838", "PickFromInventory"); 45 | PACKET_MAP.put("class_2840", "CraftRequest"); 46 | PACKET_MAP.put("class_2842", "UpdatePlayerAbilities"); 47 | PACKET_MAP.put("class_2846", "PlayerAction"); 48 | PACKET_MAP.put("class_2848", "ClientCommand"); 49 | PACKET_MAP.put("class_2851", "PlayerInput"); 50 | PACKET_MAP.put("class_2853", "RecipeBookData"); 51 | PACKET_MAP.put("class_2855", "RenameItem"); 52 | PACKET_MAP.put("class_2856", "ResourcePackStatus"); 53 | PACKET_MAP.put("class_2859", "AdvancementTab"); 54 | PACKET_MAP.put("class_2863", "SelectMerchantTrade"); 55 | PACKET_MAP.put("class_2866", "UpdateBeacon"); 56 | PACKET_MAP.put("class_2868", "UpdateSelectedSlot"); 57 | PACKET_MAP.put("class_2870", "UpdateCommandBlock"); 58 | PACKET_MAP.put("class_2871", "UpdateCommandBlockMinecart"); 59 | PACKET_MAP.put("class_2873", "CreativeInventoryAction"); 60 | PACKET_MAP.put("class_2875", "UpdateStructureBlock"); 61 | PACKET_MAP.put("class_2877", "UpdateSign"); 62 | PACKET_MAP.put("class_2879", "HandSwing"); 63 | PACKET_MAP.put("class_2884", "SpectatorTeleport"); 64 | PACKET_MAP.put("class_2885", "PlayerInteractBlock"); 65 | PACKET_MAP.put("class_2886", "PlayerInteractItem"); 66 | PACKET_MAP.put("class_2889", "Handshake"); 67 | PACKET_MAP.put("class_2913", "LoginQueryResponse"); 68 | PACKET_MAP.put("class_2915", "LoginHello"); 69 | PACKET_MAP.put("class_2917", "LoginKey"); 70 | PACKET_MAP.put("class_2935", "QueryPing"); 71 | PACKET_MAP.put("class_2937", "QueryRequest"); 72 | PACKET_MAP.put("class_3753", "UpdateJigsaw"); 73 | PACKET_MAP.put("class_4210", "UpdateDifficulty"); 74 | PACKET_MAP.put("class_4211", "UpdateDifficultyLock"); 75 | PACKET_MAP.put("class_5194", "JigsawGenerating"); 76 | PACKET_MAP.put("class_5427", "RecipeCategoryOptions"); 77 | PACKET_MAP.put("class_6374", "CommonPong"); 78 | PACKET_MAP.put("class_7472", "CommandExecution"); 79 | PACKET_MAP.put("class_7640", "MessageAcknowledgment"); 80 | PACKET_MAP.put("class_7861", "PlayerSession"); 81 | PACKET_MAP.put("class_8590", "AcknowledgeChunks"); 82 | PACKET_MAP.put("class_8591", "AcknowledgeReconfiguration"); 83 | PACKET_MAP.put("class_8593", "EnterConfiguration"); 84 | PACKET_MAP.put("class_8736", "Ready"); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/org/cmdutils/util/FontUtil.java: -------------------------------------------------------------------------------- 1 | package org.cmdutils.util; 2 | 3 | import java.awt.*; 4 | 5 | public class FontUtil { 6 | public static final Font AWT_MONOSPACE = new Font(Font.MONOSPACED, Font.PLAIN, 12); 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/org/cmdutils/util/Mcfw.java: -------------------------------------------------------------------------------- 1 | package org.cmdutils.util; 2 | 3 | import net.minecraft.network.packet.Packet; 4 | 5 | import java.util.ArrayList; 6 | import java.util.HashMap; 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | public class Mcfw { 11 | public static Map filteredPackets = new HashMap<>(); 12 | public static List> delayedPackets = new ArrayList<>(); 13 | 14 | public static boolean enabled = false; 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/org/cmdutils/util/McfwFilterType.java: -------------------------------------------------------------------------------- 1 | package org.cmdutils.util; 2 | 3 | public enum McfwFilterType { 4 | BLOCKED, DELAYED 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/org/cmdutils/util/Utils.java: -------------------------------------------------------------------------------- 1 | package org.cmdutils.util; 2 | 3 | public class Utils { 4 | public static Integer toInteger(String number) { 5 | try { 6 | return Integer.parseInt(number); 7 | } catch (Exception e) { 8 | return null; 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/resources/assets/cmd-utils/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Coderx-Gamer/cmd-utils/4d143c466034094e0d48caf83dcecfc19cdaa0ac/src/main/resources/assets/cmd-utils/icon.png -------------------------------------------------------------------------------- /src/main/resources/assets/cmd-utils/lang/en_us.json: -------------------------------------------------------------------------------- 1 | { 2 | "key.terminal": "Open Terminal", 3 | "key.categories.cmdutils": "CMD-Utils" 4 | } -------------------------------------------------------------------------------- /src/main/resources/cmd-utils.accesswidener: -------------------------------------------------------------------------------- 1 | accessWidener v1 named 2 | 3 | accessible field net/minecraft/client/option/KeyBinding boundKey Lnet/minecraft/client/util/InputUtil$Key; -------------------------------------------------------------------------------- /src/main/resources/cmd-utils.mixins.json: -------------------------------------------------------------------------------- 1 | { 2 | "required": true, 3 | "package": "org.cmdutils.mixin", 4 | "compatibilityLevel": "JAVA_17", 5 | "client": [ 6 | "ClientConnectionMixin", 7 | "ScreenMixin", 8 | "accessor.SessionAccessor" 9 | ], 10 | "injectors": { 11 | "defaultRequire": 1 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/resources/fabric.mod.json: -------------------------------------------------------------------------------- 1 | { 2 | "schemaVersion": 1, 3 | "id": "cmd-utils", 4 | "version": "${version}", 5 | "name": "CMD Utils", 6 | "description": "A FabricMC Minecraft modification used for glitch hunting.", 7 | 8 | "authors": [ 9 | "Coderx_Gamer" 10 | ], 11 | 12 | "contact": { 13 | "homepage": "https://github.com/Coderx-Gamer/cmd-utils/", 14 | "sources": "https://github.com/Coderx-Gamer/cmd-utils/" 15 | }, 16 | 17 | "license": "GPL-3.0", 18 | "icon": "assets/cmd-utils/icon.png", 19 | "environment": "client", 20 | "entrypoints": { 21 | "client": [ 22 | "org.cmdutils.MainClient" 23 | ] 24 | }, 25 | 26 | "mixins": [ 27 | "cmd-utils.mixins.json" 28 | ], 29 | 30 | "accessWidener": "cmd-utils.accesswidener", 31 | 32 | "depends": { 33 | "fabricloader": ">=0.14.24", 34 | "minecraft": "~1.20.2", 35 | "java": ">=17", 36 | "fabric-api": "*" 37 | }, 38 | 39 | "suggests": { 40 | "another-mod": "*" 41 | }, 42 | 43 | "custom": { 44 | "modmenu:clientsideOnly": true, 45 | "modmenu:api": false 46 | } 47 | } 48 | --------------------------------------------------------------------------------