├── .gitignore ├── BON_LICENSE.txt ├── GSON_LICENSE.txt ├── LICENSE ├── MCPMappingViewer.ico ├── README.md ├── build.gradle ├── change.log ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── src └── main ├── java ├── bspkrs │ └── mmv │ │ ├── ClassSrgData.java │ │ ├── CsvData.java │ │ ├── CsvFile.java │ │ ├── ExcData.java │ │ ├── ExcFile.java │ │ ├── FieldSrgData.java │ │ ├── McpBotCommand.java │ │ ├── McpMappingLoader.java │ │ ├── MemberSrgData.java │ │ ├── MethodSrgData.java │ │ ├── ParamCsvData.java │ │ ├── ParamCsvFile.java │ │ ├── RemoteZipHandler.java │ │ ├── SplittedNaturalComparator.java │ │ ├── SrgFile.java │ │ ├── StaticMethodsFile.java │ │ ├── TSrgFile.java │ │ ├── VersionFetcher.java │ │ ├── gui │ │ ├── BrowseActionListener.java │ │ ├── MappingGui.java │ │ └── TableColumnAdjuster.java │ │ └── version │ │ ├── AppVersionChecker.java │ │ └── NaturalOrderComparator.java └── immibis │ └── bon │ ├── IProgressListener.java │ ├── NameSet.java │ └── gui │ ├── Reference.java │ └── Side.java └── resources └── bspkrs └── mmv └── gui └── icon ├── bspkrs.png ├── bspkrs128.png ├── bspkrs16.png ├── bspkrs24.png ├── bspkrs32.png ├── bspkrs48.png └── bspkrs64.png /.gitignore: -------------------------------------------------------------------------------- 1 | # package 2 | *.jar 3 | 4 | # eclipse 5 | .classpath 6 | .project 7 | .metadata/ 8 | .settings/ 9 | .recommenders/ 10 | bin/ 11 | 12 | # (no) idea 13 | .idea 14 | *.iml 15 | *.ipr 16 | *.iws 17 | out/ 18 | 19 | # gradle 20 | /.gradle/ 21 | /build/ 22 | !/gradle/wrapper/gradle-wrapper.jar 23 | 24 | dist 25 | -------------------------------------------------------------------------------- /BON_LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (C) 2013 Alex "immibis" Campbell 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /GSON_LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2014 bspkrs 2 | Portions Copyright (C) 2014 Alex "immibis" Campbell 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /MCPMappingViewer.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bspkrs/MCPMappingViewer/756b6bd16fcc7bb1eb60fd9b78796cd9aee4277f/MCPMappingViewer.ico -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | *** This project is no longer maintained *** 2 | 3 | MCP Mapping Viewer 4 | ================= 5 | A small GUI for viewing the mappings from Minecraft obfuscated code names to MCP code names. 6 | 7 | ### Links of Interest 8 | - [Official Minecraft Forum Thread](http://www.minecraftforum.net/topic/2115030-) 9 | - [Binary Downloads](http://bspk.rs/MC/MCPMappingViewer/index.html) 10 | - [Issue Tracking System](https://github.com/bspkrs/MCPMappingViewer/issues) 11 | 12 | * * * 13 | 14 | #### How to build from the source code #### 15 | 16 | Run `gradlew build` from your favorite command line facilities 17 | 18 | * * * 19 | 20 | Copyright (C) 2013-2022 bspkrs
21 | Portions Copyright (C) 2013 Alex "immibis" Campbell (see BON_LICENSE.txt for details) 22 | GSON is licensed under the Apache License 2.0 (see GSON_LICENSE.txt for details) 23 | 24 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 25 | 26 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 27 | 28 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 29 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | id 'java-library' 4 | id 'eclipse' 5 | id 'idea' 6 | id 'com.github.johnrengelman.shadow' version '7.0.0' 7 | id 'edu.sc.seis.launch4j' version '2.5.0' 8 | } 9 | 10 | version = '1.0.3' 11 | ext.mainClassName = "bspkrs.mmv.gui.MappingGui" 12 | 13 | java { 14 | toolchain { 15 | languageVersion = JavaLanguageVersion.of(8) 16 | } 17 | } 18 | 19 | repositories { 20 | mavenCentral() 21 | } 22 | 23 | dependencies { 24 | implementation 'com.google.code.gson:gson:2.8.6' 25 | } 26 | 27 | [compileJava, compileTestJava].each { cJava -> 28 | cJava.options.compilerArgs += ['-Xlint:unchecked'] 29 | cJava.options.encoding = 'UTF-8' 30 | cJava.options.incremental = true 31 | cJava.options.fork = true 32 | } 33 | 34 | processResources { 35 | from 'LICENSE' 36 | } 37 | 38 | build.dependsOn(shadowJar) 39 | 40 | jar { 41 | destinationDirectory = temporaryDir 42 | } 43 | 44 | shadowJar { 45 | archiveClassifier.set('') 46 | } 47 | 48 | wrapper { 49 | distributionType = Wrapper.DistributionType.ALL 50 | } 51 | 52 | jar.manifest { 53 | attributes 'Main-Class': mainClassName 54 | } 55 | 56 | createExe { 57 | dependsOn 'build' 58 | mainClassName = mainClassName 59 | copyConfigurable = project.tasks.shadowJar.outputs.files 60 | jar = "lib/${project.tasks.shadowJar.archiveFileName}" 61 | outputDir = 'libs' 62 | outfile = tasks.shadowJar.archiveName - '.jar' + '.exe' 63 | productName = 'MCP Mapping Viewer' 64 | icon = "${projectDir}/MCPMappingViewer.ico" 65 | supportUrl = 'https://www.minecraftforum.net/topic/2115030' 66 | copyright = 'Copyright 2013-2021 bspkrs, portions Copyright 2013-2014 Alex "Immibis" Campbell' 67 | version = "${project.version}" 68 | } 69 | 70 | task run(type: JavaExec) { 71 | classpath = sourceSets.main.runtimeClasspath 72 | 73 | main = mainClassName 74 | } 75 | -------------------------------------------------------------------------------- /change.log: -------------------------------------------------------------------------------- 1 | 0.7.3 - 30-Jun-2014 2 | - fixed version checker derping due to dropbox server changes 3 | 0.7.2 - 18-Apr-2014 4 | - fixed derp where column sort settings were reset on search 5 | 0.7.1 - 12-Apr-2014 6 | - fixed compabibility with latest Forge releases 7 | 0.7.0 - 01-Apr-2014 8 | - fixed a potential issue with not adding the header row when exporting CSV files 9 | - added support for viewing and editing params.csv :D 10 | 0.6.1 - 24-Feb-2014 11 | - added code to make SRG name searches actually highlight the item they are meant to find 12 | 0.6.0 - 22-Jan-2014 13 | - saving of edits back to CSVs is now possible! careful if you are editing Forge CSVs! 14 | - when using side Universal (Forge), edits will produce multiple bot commands unless the item is client only 15 | - better handling of button states based on edits 16 | 0.5.3 - 05-Dec-2013 17 | - added application icon and About image 18 | - cleaned up some messy code 19 | - filter is now clear on load 20 | 0.5.2 - 03-Dec-2013 21 | - added search history 22 | 0.5.1 - 26-Nov-2013 23 | - fixed derp in method to get the bot command 24 | 0.5.0 - 25-Nov-2013 25 | - added basic support for generating MCPBot commands to execute in a DCC session with the bot 26 | 0.2.2 - 14-Nov-2013 27 | - proper fixed CsvFile parser defect 28 | 0.2.1 - 14-Nov-2013 29 | - fixed major logic flaw in CsvFile parser 30 | 0.2.0 - 14-Nov-2013 31 | - many UI improvements and tweaks 32 | - column sort is now remembered 33 | - added global search functionality 34 | - added option to force reload from mcp/conf files vs cached data 35 | - added version notifications (non-naggy, you'll only be notified once per new version) 36 | - improved exception handling 37 | 0.1.0a - 12-Nov-2013 38 | - initial release! 39 | - acts as an obfuscation map viewer -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bspkrs/MCPMappingViewer/756b6bd16fcc7bb1eb60fd9b78796cd9aee4277f/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-7.0-all.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or 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 UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | 86 | # Determine the Java command to use to start the JVM. 87 | if [ -n "$JAVA_HOME" ] ; then 88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 89 | # IBM's JDK on AIX uses strange locations for the executables 90 | JAVACMD="$JAVA_HOME/jre/sh/java" 91 | else 92 | JAVACMD="$JAVA_HOME/bin/java" 93 | fi 94 | if [ ! -x "$JAVACMD" ] ; then 95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 96 | 97 | Please set the JAVA_HOME variable in your environment to match the 98 | location of your Java installation." 99 | fi 100 | else 101 | JAVACMD="java" 102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 103 | 104 | Please set the JAVA_HOME variable in your environment to match the 105 | location of your Java installation." 106 | fi 107 | 108 | # Increase the maximum file descriptors if we can. 109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 110 | MAX_FD_LIMIT=`ulimit -H -n` 111 | if [ $? -eq 0 ] ; then 112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 113 | MAX_FD="$MAX_FD_LIMIT" 114 | fi 115 | ulimit -n $MAX_FD 116 | if [ $? -ne 0 ] ; then 117 | warn "Could not set maximum file descriptor limit: $MAX_FD" 118 | fi 119 | else 120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 121 | fi 122 | fi 123 | 124 | # For Darwin, add options to specify how the application appears in the dock 125 | if $darwin; then 126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 127 | fi 128 | 129 | # For Cygwin or MSYS, switch paths to Windows format before running java 130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 133 | 134 | JAVACMD=`cygpath --unix "$JAVACMD"` 135 | 136 | # We build the pattern for arguments to be converted via cygpath 137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 138 | SEP="" 139 | for dir in $ROOTDIRSRAW ; do 140 | ROOTDIRS="$ROOTDIRS$SEP$dir" 141 | SEP="|" 142 | done 143 | OURCYGPATTERN="(^($ROOTDIRS))" 144 | # Add a user-defined pattern to the cygpath arguments 145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 147 | fi 148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 149 | i=0 150 | for arg in "$@" ; do 151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 153 | 154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 156 | else 157 | eval `echo args$i`="\"$arg\"" 158 | fi 159 | i=`expr $i + 1` 160 | done 161 | case $i in 162 | 0) set -- ;; 163 | 1) set -- "$args0" ;; 164 | 2) set -- "$args0" "$args1" ;; 165 | 3) set -- "$args0" "$args1" "$args2" ;; 166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;; 167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 172 | esac 173 | fi 174 | 175 | # Escape application args 176 | save () { 177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 178 | echo " " 179 | } 180 | APP_ARGS=`save "$@"` 181 | 182 | # Collect all arguments for the java command, following the shell quoting and substitution rules 183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 184 | 185 | exec "$JAVACMD" "$@" 186 | -------------------------------------------------------------------------------- /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 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /src/main/java/bspkrs/mmv/ClassSrgData.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 bspkrs 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 5 | * files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 7 | * Software is furnished to do so, subject to the following conditions: 8 | * 9 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 12 | * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 13 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 14 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | */ 16 | package bspkrs.mmv; 17 | 18 | public class ClassSrgData implements Comparable 19 | { 20 | public static enum SortType 21 | { 22 | PKG, 23 | OBF 24 | } 25 | 26 | private final String obfName; 27 | private final String srgName; 28 | private String srgPkgName; 29 | private final boolean isClientOnly; 30 | 31 | public static SortType sortType = SortType.PKG; 32 | 33 | public ClassSrgData(String obfName, String srgName, String srgPkgName, boolean isClientOnly) 34 | { 35 | this.obfName = obfName; 36 | this.srgName = srgName; 37 | this.srgPkgName = srgPkgName; 38 | this.isClientOnly = isClientOnly; 39 | } 40 | 41 | public String getObfName() 42 | { 43 | return this.obfName; 44 | } 45 | 46 | public String getSrgName() 47 | { 48 | return this.srgName; 49 | } 50 | 51 | public String getSrgPkgName() 52 | { 53 | return this.srgPkgName; 54 | } 55 | 56 | public ClassSrgData setSrgPkgName(String pkg) 57 | { 58 | this.srgPkgName = pkg; 59 | return this; 60 | } 61 | 62 | public boolean isClientOnly() 63 | { 64 | return isClientOnly; 65 | } 66 | 67 | public String getFullyQualifiedSrgName() 68 | { 69 | return srgPkgName + "/" + srgName; 70 | } 71 | 72 | @Override 73 | public int compareTo(ClassSrgData o) 74 | { 75 | if (sortType == SortType.PKG) 76 | if (o != null) 77 | return getFullyQualifiedSrgName().compareTo(o.getFullyQualifiedSrgName()); 78 | else 79 | return 1; 80 | else if (o != null) 81 | if (obfName.length() != o.obfName.length()) 82 | return obfName.length() - o.obfName.length(); 83 | else 84 | return obfName.compareTo(o.obfName); 85 | else 86 | return 1; 87 | 88 | } 89 | 90 | public boolean contains(String s) 91 | { 92 | return srgName.contains(s) || obfName.contains(s) || this.srgPkgName.contains(s); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/bspkrs/mmv/CsvData.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 bspkrs 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 5 | * files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 7 | * Software is furnished to do so, subject to the following conditions: 8 | * 9 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 12 | * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 13 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 14 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | */ 16 | package bspkrs.mmv; 17 | 18 | public class CsvData implements Comparable 19 | { 20 | private final String srgName; 21 | private String mcpName; 22 | private final int side; 23 | private String comment; 24 | private boolean needsQuoted; 25 | 26 | public CsvData(String srgName, String mcpName, int side, String comment) 27 | { 28 | this.srgName = srgName; 29 | this.mcpName = mcpName; 30 | this.side = side; 31 | 32 | if (comment.contains(",") || (!comment.isEmpty() && comment.charAt(0) == '"' && comment.charAt(comment.length() - 1) == '"')) 33 | { 34 | needsQuoted = true; 35 | if (comment.charAt(0) == '"' && comment.charAt(comment.length() - 1) == '"') 36 | this.comment = comment.substring(1, comment.length() - 1); 37 | else 38 | this.comment = comment; 39 | } 40 | else 41 | { 42 | this.comment = comment; 43 | needsQuoted = false; 44 | } 45 | } 46 | 47 | public String toCsv() 48 | { 49 | return srgName + "," + mcpName + "," + side + "," + (needsQuoted ? "\"" + comment + "\"" : comment); 50 | } 51 | 52 | public String getSrgName() 53 | { 54 | return srgName; 55 | } 56 | 57 | public String getMcpName() 58 | { 59 | return mcpName; 60 | } 61 | 62 | public CsvData setMcpName(String mcpName) 63 | { 64 | this.mcpName = mcpName; 65 | return this; 66 | } 67 | 68 | public int getSide() 69 | { 70 | return side; 71 | } 72 | 73 | public String getComment() 74 | { 75 | return comment; 76 | } 77 | 78 | public CsvData setComment(String comment) 79 | { 80 | this.comment = comment; 81 | return this; 82 | } 83 | 84 | @Override 85 | public int compareTo(CsvData o) 86 | { 87 | if (o != null) 88 | return this.srgName.compareTo(o.srgName); 89 | 90 | return 1; 91 | } 92 | 93 | public boolean contains(String s) 94 | { 95 | return this.mcpName.contains(s) || this.comment.contains(s); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/main/java/bspkrs/mmv/CsvFile.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 bspkrs 3 | * Portions Copyright (C) 2014 Alex "immibis" Campbell 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 6 | * files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, 7 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 8 | * Software is furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | * 12 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 13 | * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 15 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 16 | */ 17 | package bspkrs.mmv; 18 | 19 | import java.io.BufferedReader; 20 | import java.io.File; 21 | import java.io.FileReader; 22 | import java.io.FileWriter; 23 | import java.io.IOException; 24 | import java.io.PrintWriter; 25 | import java.text.SimpleDateFormat; 26 | import java.util.Date; 27 | import java.util.Map; 28 | import java.util.Scanner; 29 | import java.util.TreeMap; 30 | 31 | public class CsvFile 32 | { 33 | private final File file; 34 | private final Map srgMemberName2CsvData; 35 | private boolean isDirty; 36 | private String headerLine; 37 | 38 | public CsvFile(File file) throws IOException 39 | { 40 | this.file = file; 41 | srgMemberName2CsvData = new TreeMap(); 42 | readFromFile(); 43 | isDirty = false; 44 | } 45 | 46 | public void readFromFile() throws IOException 47 | { 48 | Scanner in = new Scanner(new BufferedReader(new FileReader(file))); 49 | try 50 | { 51 | in.useDelimiter(","); 52 | headerLine = in.nextLine(); // Skip header row 53 | while (in.hasNextLine()) 54 | { 55 | String srgName = in.next(); 56 | String mcpName = in.next(); 57 | String side = in.next(); 58 | String comment = in.nextLine().substring(1); 59 | srgMemberName2CsvData.put(srgName, new CsvData(srgName, mcpName, Integer.valueOf(side), comment)); 60 | } 61 | } 62 | finally 63 | { 64 | in.close(); 65 | } 66 | } 67 | 68 | public void writeToFile() throws IOException 69 | { 70 | if (isDirty) 71 | { 72 | if (file.exists()) 73 | { 74 | File fileBak = new File(file.getAbsolutePath() + "_" + new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()) + ".bak"); 75 | file.renameTo(fileBak); 76 | } 77 | 78 | file.createNewFile(); 79 | 80 | PrintWriter out = new PrintWriter(new FileWriter(file)); 81 | out.println(headerLine); 82 | 83 | for (CsvData data : srgMemberName2CsvData.values()) 84 | out.println(data.toCsv()); 85 | 86 | out.close(); 87 | 88 | isDirty = false; 89 | } 90 | } 91 | 92 | public boolean hasCsvDataForKey(String srgName) 93 | { 94 | return srgMemberName2CsvData.containsKey(srgName); 95 | } 96 | 97 | public CsvData getCsvDataForKey(String srgName) 98 | { 99 | return srgMemberName2CsvData.get(srgName); 100 | } 101 | 102 | public void updateCsvDataForKey(String srgName, CsvData csvData) 103 | { 104 | srgMemberName2CsvData.put(srgName, csvData); 105 | isDirty = true; 106 | } 107 | 108 | public boolean isDirty() 109 | { 110 | return isDirty; 111 | } 112 | 113 | public void setIsDirty(boolean bol) 114 | { 115 | isDirty = bol; 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/main/java/bspkrs/mmv/ExcData.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 bspkrs 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 5 | * files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 7 | * Software is furnished to do so, subject to the following conditions: 8 | * 9 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 12 | * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 13 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 14 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | */ 16 | package bspkrs.mmv; 17 | 18 | import java.util.ArrayList; 19 | import java.util.Arrays; 20 | import java.util.regex.Matcher; 21 | import java.util.regex.Pattern; 22 | 23 | public class ExcData implements Comparable 24 | { 25 | private final String srgOwner; 26 | private final String srgName; 27 | private final String descriptor; 28 | private final String[] exceptions; 29 | private final String[] parameters; 30 | private final String[] paramTypes; 31 | 32 | public ExcData(String srgOwner, String srgName, String descriptor, String[] exceptions, String[] parameters) 33 | { 34 | this.srgOwner = srgOwner; 35 | this.srgName = srgName; 36 | this.descriptor = descriptor; 37 | this.exceptions = exceptions; 38 | paramTypes = splitMethodDesc(descriptor); 39 | this.parameters = parameters; 40 | } 41 | 42 | public ExcData(String srgOwner, String srgName, String descriptor, String[] exceptions, boolean isStatic) 43 | { 44 | this.srgOwner = srgOwner; 45 | this.srgName = srgName; 46 | this.descriptor = descriptor; 47 | this.exceptions = exceptions; 48 | paramTypes = splitMethodDesc(descriptor); 49 | parameters = genParamNames(ExcData.getSrgId(srgName), paramTypes, isStatic); 50 | } 51 | 52 | public String getSrgClassOwner() 53 | { 54 | return srgOwner; 55 | } 56 | 57 | public String getSrgMethodName() 58 | { 59 | return srgName; 60 | } 61 | 62 | public String getDescriptor() 63 | { 64 | return descriptor; 65 | } 66 | 67 | public String[] getExceptions() 68 | { 69 | return exceptions; 70 | } 71 | 72 | public String[] getParameters() 73 | { 74 | return parameters; 75 | } 76 | 77 | public String[] getParamTypes() 78 | { 79 | return paramTypes; 80 | } 81 | 82 | public boolean contains(String s) 83 | { 84 | if (srgName.contains(s)) 85 | return true; 86 | else 87 | for (String param : parameters) 88 | if (param.contains(s)) 89 | return true; 90 | 91 | return false; 92 | } 93 | 94 | @Override 95 | public int compareTo(ExcData o) 96 | { 97 | return srgName.compareTo(o.srgName); 98 | } 99 | 100 | public static String[] splitMethodDesc(String desc) 101 | { 102 | //\[*(?:L[^;]+;|[ZBCSIFDJ]) 103 | int beginIndex = desc.indexOf('('); 104 | int endIndex = desc.lastIndexOf(')'); 105 | if (((beginIndex == -1) && (endIndex != -1)) || ((beginIndex != -1) && (endIndex == -1))) 106 | { 107 | System.err.println(beginIndex); 108 | System.err.println(endIndex); 109 | throw new RuntimeException(); 110 | } 111 | String x0; 112 | if ((beginIndex == -1) && (endIndex == -1)) 113 | { 114 | x0 = desc; 115 | } 116 | else 117 | { 118 | x0 = desc.substring(beginIndex + 1, endIndex); 119 | } 120 | Pattern pattern = Pattern.compile("\\[*(?:L[^;]+;|[ZBCSIFDJ])"); 121 | Matcher matcher = pattern.matcher(x0); 122 | 123 | ArrayList listMatches = new ArrayList(); 124 | 125 | while (matcher.find()) 126 | { 127 | listMatches.add(matcher.group()); 128 | } 129 | 130 | return listMatches.toArray(new String[listMatches.size()]); 131 | } 132 | 133 | public static String[] genParamNames(String srgId, String[] paramTypes, boolean isStatic) 134 | { 135 | boolean skip2 = (paramTypes.length >= 4) && paramTypes[0].equals("Ljava/lang/String;") && paramTypes[1].equals('I') 136 | && paramTypes[0].equals(paramTypes[2]) && paramTypes[1].equals(paramTypes[3]); 137 | 138 | String[] ret = new String[paramTypes.length]; 139 | int idOffset = isStatic ? 0 : 1; 140 | if (skip2) 141 | idOffset += 2; 142 | 143 | for (int i = 0; i < paramTypes.length; i++) 144 | { 145 | ret[i] = "p_" + srgId + "_" + (i + idOffset) + "_"; 146 | if (paramTypes[i].equals("D") || paramTypes[i].equals("J")) 147 | idOffset++; 148 | } 149 | 150 | return ret; 151 | } 152 | 153 | public static String getSrgId(String srgName) 154 | { 155 | Pattern pattern = Pattern.compile("func_(i?[0-9]+)_"); 156 | Matcher matcher = pattern.matcher(srgName); 157 | if (matcher.find()) 158 | return matcher.group(1); 159 | return srgName; 160 | } 161 | 162 | @Override 163 | public String toString() 164 | { 165 | return String.format(" Owner: %s\n SRG Name: %s\n Descriptor: %s\n Exceptions: %s\n Parameters: %s\n Param Types: %s", srgOwner, srgName, descriptor, Arrays.toString(exceptions), Arrays.toString(parameters), Arrays.toString(paramTypes)); 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /src/main/java/bspkrs/mmv/ExcFile.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 bspkrs 3 | * Portions Copyright (C) 2014 Alex "immibis" Campbell 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 6 | * files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, 7 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 8 | * Software is furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | * 12 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 13 | * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 15 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 16 | */ 17 | package bspkrs.mmv; 18 | 19 | import java.io.File; 20 | import java.io.FileReader; 21 | import java.io.IOException; 22 | import java.util.HashMap; 23 | import java.util.Map; 24 | import java.util.Scanner; 25 | 26 | public class ExcFile 27 | { 28 | public final Map srgMethodName2ExcData; 29 | public final Map srgParamName2ExcData; 30 | 31 | public ExcFile(File f) throws IOException 32 | { 33 | srgMethodName2ExcData = new HashMap(); 34 | srgParamName2ExcData = new HashMap(); 35 | // example lines: 36 | // net/minecraft/util/ChunkCoordinates=CL_00001555 37 | // net/minecraft/world/chunk/storage/AnvilChunkLoader.func_75816_a(Lnet/minecraft/world/World;Lnet/minecraft/world/chunk/Chunk;)V=net/minecraft/world/MinecraftException,java/io/IOException|p_75816_1_,p_75816_2_ 38 | // net/minecraft/world/biome/BiomeGenMutated.func_150571_c(III)I=|p_150571_1_,p_150571_2_,p_150571_3_ 39 | // net/minecraft/world/chunk/storage/AnvilChunkLoader.func_75818_b()V=| 40 | // net/minecraft/server/MinecraftServer.func_145747_a(Lnet/minecraft/util/IChatComponent;)V=|p_145747_1_ 41 | 42 | Scanner in = new Scanner(new FileReader(f)); 43 | try 44 | { 45 | while (in.hasNextLine()) 46 | { 47 | if (in.hasNext("#")) 48 | { 49 | in.nextLine(); 50 | continue; 51 | } 52 | 53 | in.useDelimiter("\\."); 54 | String srgOwner = in.next(); 55 | in.useDelimiter("\\("); 56 | 57 | if (!in.hasNext()) 58 | if (in.hasNextLine()) 59 | in.nextLine(); 60 | else 61 | break; 62 | 63 | String srgName = in.next().substring(1); 64 | in.useDelimiter("="); 65 | String descriptor = in.next(); 66 | in.useDelimiter("\\|"); 67 | String excs = in.next().substring(1); 68 | String params = in.nextLine().substring(1); 69 | 70 | ExcData toAdd = new ExcData(srgOwner, srgName, descriptor, 71 | (excs.length() > 0 ? excs.split(",") : new String[0]), 72 | (params.length() > 0 ? params.split(",") : new String[0])); 73 | 74 | ExcData existing = srgMethodName2ExcData.get(srgName); 75 | 76 | if ((existing == null) || (existing.getParameters().length < toAdd.getParameters().length)) 77 | { 78 | srgMethodName2ExcData.put(srgName, toAdd); 79 | 80 | for (String parameter : toAdd.getParameters()) 81 | srgParamName2ExcData.put(parameter, toAdd); 82 | } 83 | } 84 | } 85 | finally 86 | { 87 | in.close(); 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/main/java/bspkrs/mmv/FieldSrgData.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 bspkrs 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 5 | * files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 7 | * Software is furnished to do so, subject to the following conditions: 8 | * 9 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 12 | * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 13 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 14 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | */ 16 | package bspkrs.mmv; 17 | 18 | public class FieldSrgData extends MemberSrgData implements Comparable 19 | { 20 | public FieldSrgData(String obfOwner, String obfName, String srgOwner, String srgPkg, String srgName, boolean isClientOnly) 21 | { 22 | super(obfOwner, obfName, srgOwner, srgPkg, srgName, isClientOnly); 23 | } 24 | 25 | @Override 26 | public int compareTo(FieldSrgData o) 27 | { 28 | if (o != null) 29 | return this.getSrgName().compareTo(o.getSrgName()); 30 | else 31 | return 1; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/bspkrs/mmv/McpBotCommand.java: -------------------------------------------------------------------------------- 1 | package bspkrs.mmv; 2 | 3 | public class McpBotCommand 4 | { 5 | public enum BotCommand 6 | { 7 | SF, 8 | SM, 9 | SP, 10 | FSF, 11 | FSM, 12 | FSP; 13 | } 14 | 15 | public enum MemberType 16 | { 17 | FIELD, 18 | METHOD, 19 | PARAM; 20 | } 21 | 22 | public static BotCommand getCommand(MemberType type, boolean isForced) 23 | { 24 | switch (type) 25 | { 26 | case METHOD: 27 | return isForced ? BotCommand.FSM : BotCommand.SM; 28 | case PARAM: 29 | return isForced ? BotCommand.FSP : BotCommand.SP; 30 | default: 31 | return isForced ? BotCommand.FSF : BotCommand.SF; 32 | } 33 | } 34 | 35 | private final BotCommand command; 36 | private final String srgName; 37 | private final String newName; 38 | private final String comment; 39 | 40 | public McpBotCommand(BotCommand command, String srgName, String newName, String comment) 41 | { 42 | this.command = command; 43 | this.srgName = srgName; 44 | this.newName = newName; 45 | this.comment = comment; 46 | } 47 | 48 | public McpBotCommand(BotCommand command, String srgName, String newName) 49 | { 50 | this(command, srgName, newName, ""); 51 | } 52 | 53 | public static McpBotCommand getMcpBotCommand(MemberType type, boolean isForced, String srgName, String newName, String comment) 54 | { 55 | return new McpBotCommand(getCommand(type, isForced), srgName, newName, comment); 56 | } 57 | 58 | public BotCommand getCommand() 59 | { 60 | return command; 61 | } 62 | 63 | public String getNewName() 64 | { 65 | return newName; 66 | } 67 | 68 | @Override 69 | public String toString() 70 | { 71 | return String.format("!%s %s %s %s", command.toString().toLowerCase(), srgName, newName, comment); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/bspkrs/mmv/McpMappingLoader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 bspkrs 3 | * Portions Copyright (C) 2014 Alex "immibis" Campbell 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 6 | * files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, 7 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 8 | * Software is furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | * 12 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 13 | * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 15 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 16 | */ 17 | package bspkrs.mmv; 18 | 19 | import immibis.bon.IProgressListener; 20 | 21 | import java.io.File; 22 | import java.io.IOException; 23 | import java.security.DigestException; 24 | import java.security.NoSuchAlgorithmException; 25 | import java.util.Collection; 26 | import java.util.Map; 27 | import java.util.Map.Entry; 28 | import java.util.Set; 29 | import java.util.TreeMap; 30 | import java.util.TreeSet; 31 | 32 | import javax.swing.table.AbstractTableModel; 33 | import javax.swing.table.TableModel; 34 | 35 | import bspkrs.mmv.McpBotCommand.MemberType; 36 | import bspkrs.mmv.gui.MappingGui; 37 | 38 | public class McpMappingLoader 39 | { 40 | 41 | public static class CantLoadMCPMappingException extends Exception 42 | { 43 | private static final long serialVersionUID = 1; 44 | 45 | public CantLoadMCPMappingException(String reason) 46 | { 47 | super(reason); 48 | } 49 | } 50 | 51 | private final File baseDir = new File(new File(System.getProperty("user.home")), ".cache/MCPMappingViewer"); 52 | private final String baseSrgDir = "{mc_ver}"; 53 | private final String baseMappingDir = "{mc_ver}/{channel}_{map_ver}"; 54 | private final String baseMappingUrl = "https://maven.minecraftforge.net/de/oceanlabs/mcp/mcp_{channel}/{map_ver}-{mc_ver}/mcp_{channel}-{map_ver}-{mc_ver}.zip"; 55 | private final String newBaseSrgUrl = "https://maven.minecraftforge.net/de/oceanlabs/mcp/mcp_config/{mc_ver}/mcp_config-{mc_ver}.zip"; 56 | private final String oldBaseSrgUrl = "https://maven.minecraftforge.net/de/oceanlabs/mcp/mcp/{mc_ver}/mcp-{mc_ver}-srg.zip"; 57 | 58 | private final File srgDir; 59 | private final File mappingDir; 60 | private final File srgFile; 61 | private final File excFile; 62 | private final File staticMethodsFile; 63 | private SrgFile srgFileData; 64 | private ExcFile excFileData; 65 | private StaticMethodsFile staticMethods; 66 | private CsvFile csvFieldData, csvMethodData; 67 | private ParamCsvFile csvParamData; 68 | private final MappingGui parentGui; 69 | private final Map commandMap = new TreeMap(); // srgName -> McpBotCommand 70 | public final Map srgMethodData2CsvData = new TreeMap(); 71 | public final Map srgFieldData2CsvData = new TreeMap(); 72 | public final Map> excData2MapParamCsvData = new TreeMap>(); 73 | 74 | public McpMappingLoader(MappingGui parentGui, String mappingString, IProgressListener progress) throws IOException, CantLoadMCPMappingException, NoSuchAlgorithmException, DigestException 75 | { 76 | progress.setMax(6); 77 | progress.set(0); 78 | this.parentGui = parentGui; 79 | 80 | // mappingString: __, eg, 1.8_snapshot_20151118 81 | String[] tokens = mappingString.split("_"); 82 | if (tokens.length < 3) 83 | throw new CantLoadMCPMappingException("Invalid mapping string specified."); 84 | 85 | boolean isNew = tokens[0].compareTo("1.13") >= 0; 86 | if (tokens[0].contains("1.9") || tokens[0].contains("1.8") || tokens[0].contains("1.7")) 87 | isNew = false; 88 | 89 | String baseSrgUrl = isNew ? newBaseSrgUrl : oldBaseSrgUrl; 90 | String srgFileName = isNew ? "config/joined.tsrg" : "joined.srg"; 91 | String excFileName = isNew ? "config/exceptions.txt" : "joined.exc"; 92 | String staticMethodsFileName = isNew ? "config/static_methods.txt" : "static_methods.txt"; 93 | 94 | progress.set(0, "Fetching SRG data"); 95 | srgDir = getSubDirForZip(tokens, baseSrgUrl, baseSrgDir); 96 | progress.set(1, "Fetching CSV data"); 97 | mappingDir = getSubDirForZip(tokens, baseMappingUrl, baseMappingDir); 98 | 99 | srgFile = new File(srgDir, srgFileName); 100 | excFile = new File(srgDir, excFileName); 101 | staticMethodsFile = new File(srgDir, staticMethodsFileName); 102 | 103 | if (!srgFile.exists()) 104 | throw new CantLoadMCPMappingException("Unable to find joined.srg. Your MCP conf folder may be corrupt."); 105 | 106 | if (!excFile.exists()) 107 | throw new CantLoadMCPMappingException("Unable to find joined.exc. Your MCP conf folder may be corrupt."); 108 | 109 | if (!staticMethodsFile.exists()) 110 | throw new CantLoadMCPMappingException("Unable to find static_methods.txt. Your MCP conf folder may be corrupt."); 111 | 112 | progress.set(2, "Loading CSV data"); 113 | loadCsvMapping(); 114 | progress.set(3, "Loading SRG data"); 115 | loadSrgMapping(isNew); 116 | progress.set(4, "Linking SRG data with CSV data"); 117 | linkSrgDataToCsvData(); 118 | progress.set(5, "Linking EXC data with CSV data"); 119 | linkExcDataToSetParamCsvData(); 120 | } 121 | 122 | private File getSubDirForZip(String[] tokens, String baseZipUrl, String baseSubDir) throws CantLoadMCPMappingException, NoSuchAlgorithmException, DigestException, IOException 123 | { 124 | if (!baseDir.exists() && !baseDir.mkdirs()) 125 | throw new CantLoadMCPMappingException("Application data folder does not exist and cannot be created."); 126 | 127 | File subDir = new File(baseDir, replaceTokens(baseSubDir, tokens)); 128 | if (!subDir.exists() && !subDir.mkdirs()) 129 | throw new CantLoadMCPMappingException("Data folder does not exist and cannot be created."); 130 | 131 | RemoteZipHandler rzh = new RemoteZipHandler(replaceTokens(baseZipUrl, tokens), subDir, "SHA1"); 132 | rzh.checkRemoteZip(); 133 | 134 | return subDir; 135 | } 136 | 137 | private String replaceTokens(String s, String[] tokens) 138 | { 139 | return s.replace("{mc_ver}", tokens[0]).replace("{channel}", tokens[1]).replace("{map_ver}", tokens[2]); 140 | } 141 | 142 | private void loadSrgMapping(boolean newFormat) throws IOException 143 | { 144 | staticMethods = new StaticMethodsFile(staticMethodsFile); 145 | excFileData = new ExcFile(excFile); 146 | srgFileData = newFormat 147 | ? new TSrgFile(srgFile, excFileData, staticMethods) 148 | : new SrgFile(srgFile, excFileData, staticMethods); 149 | } 150 | 151 | private void loadCsvMapping() throws IOException 152 | { 153 | csvFieldData = new CsvFile(new File(mappingDir, "fields.csv")); 154 | csvMethodData = new CsvFile(new File(mappingDir, "methods.csv")); 155 | csvParamData = new ParamCsvFile(new File(mappingDir, "params.csv")); 156 | } 157 | 158 | private void linkSrgDataToCsvData() 159 | { 160 | for (Entry methodData : srgFileData.srgMethodName2MethodData.entrySet()) 161 | { 162 | if (!srgMethodData2CsvData.containsKey(methodData.getValue()) && csvMethodData.hasCsvDataForKey(methodData.getKey())) 163 | { 164 | srgMethodData2CsvData.put(methodData.getValue(), csvMethodData.getCsvDataForKey(methodData.getKey())); 165 | } 166 | else if (srgMethodData2CsvData.containsKey(methodData.getValue())) 167 | System.out.println("SRG method " + methodData.getKey() + " has multiple entries in CSV file!"); 168 | } 169 | 170 | for (Entry fieldData : srgFileData.srgFieldName2FieldData.entrySet()) 171 | { 172 | if (!srgFieldData2CsvData.containsKey(fieldData.getValue()) && csvFieldData.hasCsvDataForKey(fieldData.getKey())) 173 | { 174 | srgFieldData2CsvData.put(fieldData.getValue(), csvFieldData.getCsvDataForKey(fieldData.getKey())); 175 | } 176 | else if (srgFieldData2CsvData.containsKey(fieldData.getValue())) 177 | System.out.println("SRG field " + fieldData.getKey() + " has multiple entries in CSV file!"); 178 | } 179 | } 180 | 181 | private void linkExcDataToSetParamCsvData() 182 | { 183 | for (Entry excData : excFileData.srgMethodName2ExcData.entrySet()) 184 | { 185 | if (!excData2MapParamCsvData.containsKey(excData.getValue()) && excData.getValue().getParameters().length > 0) 186 | { 187 | TreeMap params = new TreeMap(); 188 | for (String srgName : excData.getValue().getParameters()) 189 | if (csvParamData.hasCsvDataForKey(srgName)) 190 | params.put(srgName, csvParamData.getCsvDataForKey(srgName)); 191 | 192 | excData2MapParamCsvData.put(excData.getValue(), params); 193 | } 194 | else if (excData2MapParamCsvData.containsKey(excData.getValue())) 195 | System.out.println("EXC method param " + excData.getKey() + " has multiple entries in CSV file!"); 196 | } 197 | } 198 | 199 | private CsvData processMemberDataEdit(MemberType type, Map srg2MemberData, 200 | Map memberData2CsvData, 201 | String srgName, String mcpName, String comment) 202 | { 203 | MemberSrgData memberData = srg2MemberData.get(srgName); 204 | CsvData csvData = null; 205 | 206 | if (memberData != null) 207 | { 208 | boolean isForced = memberData2CsvData.containsKey(memberData); 209 | if (isForced) 210 | { 211 | csvData = memberData2CsvData.get(memberData); 212 | if (!mcpName.trim().equals(csvData.getMcpName()) || !comment.trim().equals(csvData.getComment())) 213 | { 214 | csvData.setMcpName(mcpName.trim()); 215 | csvData.setComment(comment.trim()); 216 | } 217 | else 218 | return null; 219 | } 220 | else 221 | { 222 | csvData = new CsvData(srgName, mcpName.trim(), 2, comment.trim()); 223 | } 224 | 225 | commandMap.put(srgName, McpBotCommand.getMcpBotCommand(type, isForced, csvData.getSrgName(), csvData.getMcpName(), csvData.getComment())); 226 | } 227 | 228 | return csvData; 229 | } 230 | 231 | public String getBotCommands(boolean clear) 232 | { 233 | String r = ""; 234 | 235 | for (McpBotCommand command : commandMap.values()) 236 | r += command.toString() + "\n"; 237 | 238 | if (clear) 239 | commandMap.clear(); 240 | 241 | return r; 242 | } 243 | 244 | public boolean hasPendingCommands() 245 | { 246 | return !commandMap.isEmpty(); 247 | } 248 | 249 | public TableModel getSearchResults(String input, IProgressListener progress) 250 | { 251 | if (input == null || input.trim().isEmpty()) 252 | return getClassModel(); 253 | 254 | if (progress != null) 255 | { 256 | progress.setMax(3); 257 | progress.set(0); 258 | } 259 | 260 | Set results = new TreeSet(); 261 | 262 | // Search Class objects 263 | for (ClassSrgData classData : srgFileData.srgClassName2ClassData.values()) 264 | if (classData.contains(input)) 265 | results.add(classData); 266 | 267 | if (progress != null) 268 | progress.set(1); 269 | 270 | // Search Methods 271 | for (Entry> entry : srgFileData.class2MethodDataSet.entrySet()) 272 | { 273 | if (!results.contains(entry.getKey())) 274 | { 275 | for (MethodSrgData methodData : entry.getValue()) 276 | { 277 | CsvData csv = srgMethodData2CsvData.get(methodData); 278 | if (methodData.contains(input) || csv != null && csv.contains(input)) 279 | { 280 | results.add(entry.getKey()); 281 | break; 282 | } 283 | } 284 | } 285 | } 286 | 287 | if (progress != null) 288 | progress.set(2); 289 | 290 | // Search Fields 291 | for (Entry> entry : srgFileData.class2FieldDataSet.entrySet()) 292 | { 293 | if (!results.contains(entry.getKey())) 294 | { 295 | for (FieldSrgData fieldData : entry.getValue()) 296 | { 297 | CsvData csv = srgFieldData2CsvData.get(fieldData); 298 | if (fieldData.contains(input) || csv != null && csv.contains(input)) 299 | { 300 | results.add(entry.getKey()); 301 | break; 302 | } 303 | } 304 | } 305 | } 306 | 307 | return new ClassModel(results); 308 | } 309 | 310 | public TableModel getClassModel() 311 | { 312 | return new ClassModel(srgFileData.srgClassName2ClassData.values()); 313 | } 314 | 315 | public TableModel getMethodModel(String srgPkgAndOwner) 316 | { 317 | ClassSrgData classData = srgFileData.srgClassName2ClassData.get(srgPkgAndOwner); 318 | return new MethodModel(srgFileData.class2MethodDataSet.get(classData)); 319 | } 320 | 321 | public TableModel getParamModel(String srgMethodName) 322 | { 323 | if (excFileData.srgMethodName2ExcData.containsKey(srgMethodName)) 324 | return new ParamModel(excFileData.srgMethodName2ExcData.get(srgMethodName)); 325 | else 326 | return MappingGui.paramsDefaultModel; 327 | } 328 | 329 | public TableModel getFieldModel(String srgPkgAndOwner) 330 | { 331 | ClassSrgData classData = srgFileData.srgClassName2ClassData.get(srgPkgAndOwner); 332 | return new FieldModel(srgFileData.class2FieldDataSet.get(classData)); 333 | } 334 | 335 | @SuppressWarnings("rawtypes") 336 | public class ClassModel extends AbstractTableModel 337 | { 338 | private static final long serialVersionUID = 1L; 339 | public final String[] columnNames = { "Pkg name", "SRG name", "Obf name" }; 340 | private final Class[] columnTypes = { String.class, String.class, String.class }; 341 | private final boolean[] isColumnEditable = { false, false, false }; 342 | private final Object[][] data; 343 | private final Collection collectionRef; 344 | 345 | public ClassModel(Collection map) 346 | { 347 | collectionRef = map; 348 | 349 | data = new Object[collectionRef.size()][columnNames.length]; 350 | 351 | int i = 0; 352 | 353 | for (ClassSrgData classData : collectionRef) 354 | { 355 | data[i][0] = classData.getSrgPkgName(); 356 | data[i][1] = classData.getSrgName(); 357 | data[i][2] = classData.getObfName(); 358 | i++; 359 | } 360 | } 361 | 362 | @Override 363 | public int getRowCount() 364 | { 365 | return data.length; 366 | } 367 | 368 | @Override 369 | public int getColumnCount() 370 | { 371 | return columnNames.length; 372 | } 373 | 374 | @Override 375 | public String getColumnName(int columnIndex) 376 | { 377 | if (columnIndex < columnNames.length && columnIndex >= 0) 378 | return columnNames[columnIndex]; 379 | 380 | return ""; 381 | } 382 | 383 | @Override 384 | public Class getColumnClass(int columnIndex) 385 | { 386 | if (columnIndex < columnTypes.length && columnIndex >= 0) 387 | return columnTypes[columnIndex]; 388 | 389 | return String.class; 390 | } 391 | 392 | @Override 393 | public boolean isCellEditable(int rowIndex, int columnIndex) 394 | { 395 | if (columnIndex < isColumnEditable.length && columnIndex >= 0) 396 | return isColumnEditable[columnIndex]; 397 | 398 | return false; 399 | } 400 | 401 | @Override 402 | public Object getValueAt(int rowIndex, int columnIndex) 403 | { 404 | return data[rowIndex][Math.min(columnIndex, data[rowIndex].length - 1)]; 405 | } 406 | } 407 | 408 | @SuppressWarnings("rawtypes") 409 | public class MethodModel extends AbstractTableModel 410 | { 411 | private static final long serialVersionUID = 1L; 412 | private final String[] columnNames = { "MCP Name", "SRG Name", "Obf Name", "SRG Descriptor", "Comment" }; 413 | private final Class[] columnTypes = { String.class, String.class, String.class, String.class, String.class }; 414 | private final boolean[] isColumnEditable = { true, false, false, false, true }; 415 | private final Object[][] data; 416 | private final Set setRef; 417 | 418 | public MethodModel(Set srgMethodSet) 419 | { 420 | setRef = srgMethodSet; 421 | 422 | data = new Object[setRef.size()][columnNames.length]; 423 | 424 | int i = 0; 425 | 426 | for (MethodSrgData methodData : setRef) 427 | { 428 | CsvData csvData = srgMethodData2CsvData.get(methodData); 429 | if (csvData != null) 430 | { 431 | data[i][0] = csvData.getMcpName(); 432 | data[i][4] = csvData.getComment(); 433 | } 434 | else 435 | { 436 | data[i][0] = ""; 437 | data[i][4] = ""; 438 | } 439 | data[i][1] = methodData.getSrgName(); 440 | data[i][2] = methodData.getObfName(); 441 | data[i][3] = methodData.getSrgDescriptor(); 442 | 443 | i++; 444 | } 445 | } 446 | 447 | @Override 448 | public int getRowCount() 449 | { 450 | return data.length; 451 | } 452 | 453 | @Override 454 | public int getColumnCount() 455 | { 456 | return columnNames.length; 457 | } 458 | 459 | @Override 460 | public String getColumnName(int columnIndex) 461 | { 462 | if (columnIndex < columnNames.length && columnIndex >= 0) 463 | return columnNames[columnIndex]; 464 | 465 | return ""; 466 | } 467 | 468 | @Override 469 | public Class getColumnClass(int columnIndex) 470 | { 471 | if (columnIndex < columnTypes.length && columnIndex >= 0) 472 | return columnTypes[columnIndex]; 473 | 474 | return String.class; 475 | } 476 | 477 | @Override 478 | public boolean isCellEditable(int rowIndex, int columnIndex) 479 | { 480 | if (columnIndex < isColumnEditable.length && columnIndex >= 0) 481 | return isColumnEditable[columnIndex]; 482 | 483 | return false; 484 | } 485 | 486 | @Override 487 | public Object getValueAt(int rowIndex, int columnIndex) 488 | { 489 | return data[rowIndex][Math.min(columnIndex, data[rowIndex].length - 1)]; 490 | } 491 | 492 | @Override 493 | public void setValueAt(Object aValue, int rowIndex, int columnIndex) 494 | { 495 | data[rowIndex][columnIndex] = aValue; 496 | 497 | if (columnIndex == 4 && aValue != null && (data[rowIndex][0] == null || data[rowIndex][0].toString().trim().isEmpty())) 498 | return; // if only the comment has been set, don't bother adding a command 499 | 500 | String srgName = (String) data[rowIndex][1]; 501 | String mcpName = (String) data[rowIndex][0]; 502 | String comment = (String) data[rowIndex][4]; 503 | 504 | if (mcpName.trim().isEmpty()) 505 | return; 506 | 507 | CsvData result = processMemberDataEdit(MemberType.METHOD, srgFileData.srgMethodName2MethodData, srgMethodData2CsvData, srgName, mcpName, comment); 508 | 509 | if (result != null) 510 | { 511 | csvMethodData.updateCsvDataForKey(srgName, result); 512 | srgMethodData2CsvData.put(srgFileData.srgMethodName2MethodData.get(srgName), result); 513 | parentGui.setCsvFileEdited(true); 514 | } 515 | } 516 | } 517 | 518 | @SuppressWarnings("rawtypes") 519 | public class ParamModel extends AbstractTableModel 520 | { 521 | private static final long serialVersionUID = 1L; 522 | private final String[] columnNames = { "MCP Name", "SRG Name", "Type" }; 523 | private final Class[] columnTypes = { String.class, String.class, String.class }; 524 | private final boolean[] isColumnEditable = { true, false, false }; 525 | private final Object[][] data; 526 | 527 | public ParamModel(ExcData excData) 528 | { 529 | data = new Object[excData.getParameters().length][columnNames.length]; 530 | 531 | for (int i = 0; i < excData.getParameters().length; i++) 532 | { 533 | if (excData2MapParamCsvData.containsKey(excData) && excData2MapParamCsvData.get(excData).containsKey(excData.getParameters()[i])) 534 | data[i][0] = excData2MapParamCsvData.get(excData).get(excData.getParameters()[i]).getMcpName(); 535 | else 536 | data[i][0] = ""; 537 | 538 | data[i][1] = excData.getParameters()[i]; 539 | data[i][2] = excData.getParamTypes()[i]; 540 | //i++; 541 | } 542 | } 543 | 544 | @Override 545 | public int getRowCount() 546 | { 547 | return data.length; 548 | } 549 | 550 | @Override 551 | public int getColumnCount() 552 | { 553 | return columnNames.length; 554 | } 555 | 556 | @Override 557 | public String getColumnName(int columnIndex) 558 | { 559 | if (columnIndex < columnNames.length && columnIndex >= 0) 560 | return columnNames[columnIndex]; 561 | 562 | return ""; 563 | } 564 | 565 | @Override 566 | public Class getColumnClass(int columnIndex) 567 | { 568 | if (columnIndex < columnTypes.length && columnIndex >= 0) 569 | return columnTypes[columnIndex]; 570 | 571 | return String.class; 572 | } 573 | 574 | @Override 575 | public boolean isCellEditable(int rowIndex, int columnIndex) 576 | { 577 | if (columnIndex < isColumnEditable.length && columnIndex >= 0) 578 | return isColumnEditable[columnIndex]; 579 | 580 | return false; 581 | } 582 | 583 | @Override 584 | public Object getValueAt(int rowIndex, int columnIndex) 585 | { 586 | return data[rowIndex][Math.min(columnIndex, data[rowIndex].length - 1)]; 587 | } 588 | 589 | @Override 590 | public void setValueAt(Object aValue, int rowIndex, int columnIndex) 591 | { 592 | data[rowIndex][columnIndex] = aValue; 593 | 594 | String srgName = (String) data[rowIndex][1]; 595 | String mcpName = (String) data[rowIndex][0]; 596 | 597 | if (mcpName.trim().isEmpty()) 598 | return; 599 | 600 | ExcData excData = excFileData.srgParamName2ExcData.get(srgName); 601 | ParamCsvData csvData = null; 602 | boolean isForced = csvParamData.hasCsvDataForKey(srgName); 603 | 604 | if (isForced) 605 | { 606 | csvData = csvParamData.getCsvDataForKey(srgName); 607 | if (!mcpName.trim().equals(csvData.getMcpName())) 608 | csvData.setMcpName(mcpName.trim()); 609 | else 610 | return; 611 | } 612 | else 613 | { 614 | csvData = new ParamCsvData(srgName, mcpName, 2); 615 | excData2MapParamCsvData.get(excData).put(srgName, csvData); 616 | } 617 | 618 | commandMap.put(srgName, McpBotCommand.getMcpBotCommand(MemberType.PARAM, isForced, csvData.getSrgName(), csvData.getMcpName(), "")); 619 | 620 | csvParamData.updateCsvDataForKey(srgName, csvData); 621 | parentGui.setCsvFileEdited(true); 622 | } 623 | } 624 | 625 | @SuppressWarnings("rawtypes") 626 | public class FieldModel extends AbstractTableModel 627 | { 628 | private static final long serialVersionUID = 1L; 629 | private final String[] columnNames = { "MCP Name", "SRG Name", "Obf Name", "Comment" }; 630 | private final Class[] columnTypes = { String.class, String.class, String.class, String.class }; 631 | private final boolean[] isColumnEditable = { true, false, false, true }; 632 | private final Object[][] data; 633 | private final Set setRef; 634 | 635 | public FieldModel(Set srgFieldSet) 636 | { 637 | setRef = srgFieldSet; 638 | 639 | data = new Object[setRef.size()][columnNames.length]; 640 | 641 | int i = 0; 642 | 643 | for (FieldSrgData fieldData : setRef) 644 | { 645 | CsvData csvData = srgFieldData2CsvData.get(fieldData); 646 | if (csvData != null) 647 | { 648 | data[i][0] = csvData.getMcpName(); 649 | data[i][3] = csvData.getComment(); 650 | } 651 | else 652 | { 653 | data[i][0] = ""; 654 | data[i][3] = ""; 655 | } 656 | data[i][1] = fieldData.getSrgName(); 657 | data[i][2] = fieldData.getObfName(); 658 | 659 | i++; 660 | } 661 | } 662 | 663 | @Override 664 | public int getRowCount() 665 | { 666 | return data.length; 667 | } 668 | 669 | @Override 670 | public int getColumnCount() 671 | { 672 | return columnNames.length; 673 | } 674 | 675 | @Override 676 | public String getColumnName(int columnIndex) 677 | { 678 | if (columnIndex < columnNames.length && columnIndex >= 0) 679 | return columnNames[columnIndex]; 680 | 681 | return ""; 682 | } 683 | 684 | @Override 685 | public Class getColumnClass(int columnIndex) 686 | { 687 | if (columnIndex < columnTypes.length && columnIndex >= 0) 688 | return columnTypes[columnIndex]; 689 | 690 | return String.class; 691 | } 692 | 693 | @Override 694 | public boolean isCellEditable(int rowIndex, int columnIndex) 695 | { 696 | if (columnIndex < isColumnEditable.length && columnIndex >= 0) 697 | return isColumnEditable[columnIndex]; 698 | 699 | return false; 700 | } 701 | 702 | @Override 703 | public Object getValueAt(int rowIndex, int columnIndex) 704 | { 705 | return data[rowIndex][Math.min(columnIndex, data[rowIndex].length - 1)]; 706 | } 707 | 708 | @Override 709 | public void setValueAt(Object aValue, int rowIndex, int columnIndex) 710 | { 711 | data[rowIndex][columnIndex] = aValue; 712 | 713 | if (columnIndex == 3 && aValue != null && (data[rowIndex][0] == null || data[rowIndex][0].toString().trim().isEmpty())) 714 | return; // if only the comment has been set, don't bother adding a command 715 | 716 | String srgName = (String) data[rowIndex][1]; 717 | String mcpName = (String) data[rowIndex][0]; 718 | String comment = (String) data[rowIndex][3]; 719 | 720 | if (mcpName.trim().isEmpty()) 721 | return; 722 | 723 | CsvData result = processMemberDataEdit(MemberType.FIELD, srgFileData.srgFieldName2FieldData, srgFieldData2CsvData, srgName, mcpName, comment); 724 | 725 | if (result != null) 726 | { 727 | csvFieldData.updateCsvDataForKey(srgName, result); 728 | srgFieldData2CsvData.put(srgFileData.srgFieldName2FieldData.get(srgName), result); 729 | parentGui.setCsvFileEdited(true); 730 | } 731 | } 732 | } 733 | } 734 | -------------------------------------------------------------------------------- /src/main/java/bspkrs/mmv/MemberSrgData.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 bspkrs 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 5 | * files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 7 | * Software is furnished to do so, subject to the following conditions: 8 | * 9 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 12 | * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 13 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 14 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | */ 16 | package bspkrs.mmv; 17 | 18 | public class MemberSrgData 19 | { 20 | private final String obfOwner; 21 | private final String obfName; 22 | private final String srgOwner; 23 | private final String srgPkg; 24 | private final String srgName; 25 | private final boolean isClientOnly; 26 | 27 | public MemberSrgData(String obfOwner, String obfName, String srgOwner, String srgPkg, String srgName, boolean isClientOnly) 28 | { 29 | this.obfOwner = obfOwner; 30 | this.obfName = obfName; 31 | this.srgOwner = srgOwner; 32 | this.srgPkg = srgPkg; 33 | this.srgName = srgName; 34 | this.isClientOnly = isClientOnly; 35 | } 36 | 37 | public String getObfOwner() 38 | { 39 | return obfOwner; 40 | } 41 | 42 | public String getObfName() 43 | { 44 | return obfName; 45 | } 46 | 47 | public String getSrgOwner() 48 | { 49 | return srgOwner; 50 | } 51 | 52 | public String getSrgName() 53 | { 54 | return srgName; 55 | } 56 | 57 | public boolean isClientOnly() 58 | { 59 | return isClientOnly; 60 | } 61 | 62 | public String getSrgPkg() 63 | { 64 | return srgPkg; 65 | } 66 | 67 | public boolean contains(String s) 68 | { 69 | return srgName.contains(s) || obfName.contains(s); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/bspkrs/mmv/MethodSrgData.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 bspkrs 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 5 | * files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 7 | * Software is furnished to do so, subject to the following conditions: 8 | * 9 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 12 | * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 13 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 14 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | */ 16 | package bspkrs.mmv; 17 | 18 | 19 | public class MethodSrgData extends MemberSrgData implements Comparable 20 | { 21 | private final String obfDescriptor; 22 | private final String srgDescriptor; 23 | 24 | public MethodSrgData(String obfOwner, String obfName, String obfDescriptor, String srgOwner, String srgPkg, String srgName, String srgDescriptor, boolean isClientOnly) 25 | { 26 | super(obfOwner, obfName, srgOwner, srgPkg, srgName, isClientOnly); 27 | this.obfDescriptor = obfDescriptor; 28 | this.srgDescriptor = srgDescriptor; 29 | } 30 | 31 | public String getObfDescriptor() 32 | { 33 | return obfDescriptor; 34 | } 35 | 36 | public String getSrgDescriptor() 37 | { 38 | return srgDescriptor; 39 | } 40 | 41 | @Override 42 | public int compareTo(MethodSrgData o) 43 | { 44 | if (o != null) 45 | return getSrgName().compareTo(o.getSrgName()); 46 | else 47 | return 1; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/bspkrs/mmv/ParamCsvData.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 bspkrs 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 5 | * files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 7 | * Software is furnished to do so, subject to the following conditions: 8 | * 9 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 12 | * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 13 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 14 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | */ 16 | package bspkrs.mmv; 17 | 18 | public class ParamCsvData implements Comparable 19 | { 20 | private final String srgName; 21 | private String mcpName; 22 | private final int side; 23 | 24 | public ParamCsvData(String srgName, String mcpName, int side) 25 | { 26 | this.srgName = srgName; 27 | this.mcpName = mcpName; 28 | this.side = side; 29 | } 30 | 31 | public String toCsv() 32 | { 33 | return srgName + "," + mcpName + "," + side; 34 | } 35 | 36 | public String getSrgName() 37 | { 38 | return srgName; 39 | } 40 | 41 | public String getMcpName() 42 | { 43 | return mcpName; 44 | } 45 | 46 | public ParamCsvData setMcpName(String mcpName) 47 | { 48 | this.mcpName = mcpName; 49 | return this; 50 | } 51 | 52 | public int getSide() 53 | { 54 | return side; 55 | } 56 | 57 | @Override 58 | public int compareTo(ParamCsvData o) 59 | { 60 | if (o != null) 61 | return srgName.compareTo(o.srgName); 62 | 63 | return 1; 64 | } 65 | 66 | public boolean contains(String s) 67 | { 68 | return mcpName.contains(s); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/bspkrs/mmv/ParamCsvFile.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 bspkrs 3 | * Portions Copyright (C) 2014 Alex "immibis" Campbell 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 6 | * files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, 7 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 8 | * Software is furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | * 12 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 13 | * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 15 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 16 | */ 17 | package bspkrs.mmv; 18 | 19 | import java.io.BufferedReader; 20 | import java.io.File; 21 | import java.io.FileReader; 22 | import java.io.FileWriter; 23 | import java.io.IOException; 24 | import java.io.PrintWriter; 25 | import java.text.SimpleDateFormat; 26 | import java.util.Date; 27 | import java.util.Map; 28 | import java.util.Scanner; 29 | import java.util.TreeMap; 30 | 31 | public class ParamCsvFile 32 | { 33 | private final File file; 34 | private final Map srgParamName2ParamCsvData; 35 | private boolean isDirty; 36 | private String headerLine; 37 | 38 | public ParamCsvFile(File file) throws IOException 39 | { 40 | this.file = file; 41 | srgParamName2ParamCsvData = new TreeMap(); 42 | readFromFile(); 43 | isDirty = false; 44 | } 45 | 46 | public void readFromFile() throws IOException 47 | { 48 | Scanner in = new Scanner(new BufferedReader(new FileReader(file))); 49 | try 50 | { 51 | in.useDelimiter(","); 52 | headerLine = in.nextLine(); // Skip header row 53 | while (in.hasNextLine()) 54 | { 55 | String srgName = in.next(); 56 | String mcpName = in.next(); 57 | String side = in.nextLine().substring(1); 58 | srgParamName2ParamCsvData.put(srgName, new ParamCsvData(srgName, mcpName, Integer.valueOf(side))); 59 | } 60 | } 61 | finally 62 | { 63 | in.close(); 64 | } 65 | } 66 | 67 | public void writeToFile() throws IOException 68 | { 69 | if (isDirty) 70 | { 71 | if (file.exists()) 72 | { 73 | File fileBak = new File(file.getAbsolutePath() + "_" + new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()) + ".bak"); 74 | file.renameTo(fileBak); 75 | } 76 | 77 | file.createNewFile(); 78 | 79 | PrintWriter out = new PrintWriter(new FileWriter(file)); 80 | out.println(headerLine); 81 | 82 | for (ParamCsvData data : srgParamName2ParamCsvData.values()) 83 | out.println(data.toCsv()); 84 | 85 | out.close(); 86 | 87 | isDirty = false; 88 | } 89 | } 90 | 91 | public boolean hasCsvDataForKey(String srgName) 92 | { 93 | return srgParamName2ParamCsvData.containsKey(srgName); 94 | } 95 | 96 | public ParamCsvData getCsvDataForKey(String srgName) 97 | { 98 | return srgParamName2ParamCsvData.get(srgName); 99 | } 100 | 101 | public void updateCsvDataForKey(String srgName, ParamCsvData csvData) 102 | { 103 | srgParamName2ParamCsvData.put(srgName, csvData); 104 | isDirty = true; 105 | } 106 | 107 | public boolean isDirty() 108 | { 109 | return isDirty; 110 | } 111 | 112 | public void setIsDirty(boolean bol) 113 | { 114 | isDirty = bol; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/main/java/bspkrs/mmv/RemoteZipHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 bspkrs 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 5 | * files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 7 | * Software is furnished to do so, subject to the following conditions: 8 | * 9 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 12 | * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 13 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 14 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | */ 16 | package bspkrs.mmv; 17 | 18 | import java.io.File; 19 | import java.io.FileInputStream; 20 | import java.io.FileNotFoundException; 21 | import java.io.FileOutputStream; 22 | import java.io.FileWriter; 23 | import java.io.IOException; 24 | import java.io.InputStream; 25 | import java.io.OutputStream; 26 | import java.io.PrintWriter; 27 | import java.net.MalformedURLException; 28 | import java.net.URL; 29 | import java.net.URLConnection; 30 | import java.security.DigestException; 31 | import java.security.MessageDigest; 32 | import java.security.NoSuchAlgorithmException; 33 | import java.util.ArrayList; 34 | import java.util.List; 35 | import java.util.Scanner; 36 | import java.util.zip.ZipEntry; 37 | import java.util.zip.ZipInputStream; 38 | 39 | import bspkrs.mmv.gui.MappingGui; 40 | 41 | public class RemoteZipHandler 42 | { 43 | private final URL zipUrl; 44 | private final URL digestUrl; 45 | private final File localDir; 46 | private final String digestType; 47 | private final String zipFileName; 48 | 49 | public RemoteZipHandler(String urlString, File dir, String digestType) throws MalformedURLException 50 | { 51 | zipUrl = new URL(urlString); 52 | if (digestType != null) 53 | digestUrl = new URL(urlString + "." + digestType.toLowerCase()); 54 | else 55 | digestUrl = null; 56 | String[] tokens = urlString.split("/"); 57 | zipFileName = tokens[tokens.length - 1]; 58 | localDir = dir; 59 | this.digestType = digestType; 60 | } 61 | 62 | public void checkRemoteZip() throws IOException, NoSuchAlgorithmException, DigestException 63 | { 64 | // fetch zip file sha1 65 | boolean fetchZip = true; 66 | String remoteHash = null; 67 | File digestFile = null; 68 | if (digestType != null) 69 | { 70 | // check hash against local hash if exists 71 | remoteHash = loadTextFromURL(digestUrl, new String[] { "" })[0]; 72 | if (!remoteHash.isEmpty()) 73 | { 74 | digestFile = new File(localDir, zipFileName + "." + digestType.toLowerCase()); 75 | 76 | // if local digest exists and hashes match skip getting the zip file 77 | if (digestFile.exists()) 78 | { 79 | String existingHash = loadTextFromFile(digestFile, new String[] { "" })[0]; 80 | if (!existingHash.isEmpty() && remoteHash.equals(existingHash)) 81 | fetchZip = false; 82 | } 83 | } 84 | } 85 | 86 | if (fetchZip) 87 | { 88 | // download zip 89 | File localZip = new File(localDir, zipFileName); 90 | if (localZip.exists()) 91 | localZip.delete(); 92 | OutputStream output = new FileOutputStream(localZip); 93 | try 94 | { 95 | URLConnection uc = zipUrl.openConnection(); 96 | uc.addRequestProperty("User-Agent", "MMV/" + MappingGui.VERSION_NUMBER); 97 | byte[] buffer = new byte[1024]; // Or whatever 98 | int bytesRead; 99 | try (InputStream is = uc.getInputStream()) 100 | { 101 | while ((bytesRead = is.read(buffer)) > 0) 102 | output.write(buffer, 0, bytesRead); 103 | } 104 | } 105 | finally 106 | { 107 | output.close(); 108 | } 109 | 110 | // Check hash of downloaded file to ensure we received it correctly 111 | if (digestType != null && !remoteHash.isEmpty()) 112 | { 113 | String downloadHash = getFileDigest(new FileInputStream(localZip), digestType); 114 | if (!remoteHash.equals(downloadHash)) 115 | throw new java.security.DigestException("Remote digest does not match digest of downloaded file!"); 116 | } 117 | 118 | // extract zip file 119 | extractZip(localZip, localDir); 120 | if (localZip.exists()) 121 | localZip.delete(); 122 | 123 | // save new hash after successful extract 124 | if (digestType != null && !remoteHash.isEmpty()) 125 | { 126 | if (digestFile.exists()) 127 | digestFile.delete(); 128 | digestFile.createNewFile(); 129 | PrintWriter out = new PrintWriter(new FileWriter(digestFile)); 130 | out.print(remoteHash); 131 | out.close(); 132 | } 133 | } 134 | } 135 | 136 | public static String[] loadTextFromURL(URL url, String[] defaultValue) 137 | { 138 | List arraylist = new ArrayList(); 139 | Scanner scanner = null; 140 | try 141 | { 142 | URLConnection uc = url.openConnection(); 143 | uc.addRequestProperty("User-Agent", "MMV/" + MappingGui.VERSION_NUMBER); 144 | InputStream is = uc.getInputStream(); 145 | scanner = new Scanner(is, "UTF-8"); 146 | 147 | while (scanner.hasNextLine()) 148 | { 149 | arraylist.add(scanner.nextLine()); 150 | } 151 | } 152 | catch (Throwable e) 153 | { 154 | return defaultValue; 155 | } 156 | finally 157 | { 158 | if (scanner != null) 159 | scanner.close(); 160 | } 161 | return arraylist.toArray(new String[arraylist.size()]); 162 | } 163 | 164 | public static String[] loadTextFromFile(File file, String[] defaultValue) 165 | { 166 | ArrayList lines = new ArrayList(); 167 | 168 | Scanner scanner = null; 169 | try 170 | { 171 | scanner = new Scanner(file); 172 | while (scanner.hasNextLine()) 173 | lines.add(scanner.nextLine()); 174 | } 175 | catch (FileNotFoundException e) 176 | { 177 | return defaultValue; 178 | } 179 | finally 180 | { 181 | if (scanner != null) 182 | scanner.close(); 183 | } 184 | 185 | return lines.toArray(new String[lines.size()]); 186 | } 187 | 188 | public static String getFileDigest(InputStream is, String digestType) throws NoSuchAlgorithmException, IOException 189 | { 190 | MessageDigest md = MessageDigest.getInstance(digestType); 191 | byte[] dataBytes = new byte[1024]; 192 | 193 | int nread = 0; 194 | 195 | while ((nread = is.read(dataBytes)) != -1) 196 | md.update(dataBytes, 0, nread); 197 | 198 | is.close(); 199 | 200 | byte[] mdbytes = md.digest(); 201 | 202 | //convert the byte to hex format 203 | StringBuffer sb = new StringBuffer(""); 204 | for (int i = 0; i < mdbytes.length; i++) 205 | sb.append(Integer.toString((mdbytes[i] & 0xff) + 0x100, 16).substring(1)); 206 | return sb.toString(); 207 | } 208 | 209 | public static void extractZip(File zipFile, File destDir) throws IOException 210 | { 211 | byte[] buffer = new byte[1024]; 212 | if (!destDir.exists()) 213 | destDir.mkdirs(); 214 | 215 | ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile)); 216 | ZipEntry ze = zis.getNextEntry(); 217 | try 218 | { 219 | while (ze != null) 220 | { 221 | String fileName = ze.getName(); 222 | File newFile = new File(destDir, fileName); 223 | if (!newFile.toPath().normalize().startsWith(destDir.toPath().normalize())) { 224 | throw new IOException("Bad zip entry"); 225 | } 226 | if (ze.isDirectory()) 227 | { 228 | if (newFile.exists()) 229 | deleteDirAndContents(newFile); 230 | newFile.mkdirs(); 231 | } 232 | else 233 | { 234 | if (newFile.exists()) 235 | newFile.delete(); 236 | if (newFile.getParentFile() != null && !newFile.getParentFile().exists()) 237 | newFile.getParentFile().mkdirs(); 238 | FileOutputStream fos = new FileOutputStream(newFile); 239 | int len; 240 | while ((len = zis.read(buffer)) > 0) 241 | fos.write(buffer, 0, len); 242 | 243 | fos.close(); 244 | } 245 | ze = zis.getNextEntry(); 246 | } 247 | } 248 | finally 249 | { 250 | zis.closeEntry(); 251 | zis.close(); 252 | } 253 | } 254 | 255 | public static boolean deleteDirAndContents(File dir) 256 | { 257 | if (dir.isDirectory()) 258 | { 259 | String[] children = dir.list(); 260 | for (int i = 0; i < children.length; i++) 261 | { 262 | boolean success = deleteDirAndContents(new File(dir, children[i])); 263 | if (!success) 264 | return false; 265 | } 266 | } 267 | return dir.delete(); 268 | } 269 | } 270 | -------------------------------------------------------------------------------- /src/main/java/bspkrs/mmv/SplittedNaturalComparator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 bspkrs 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 5 | * files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 7 | * Software is furnished to do so, subject to the following conditions: 8 | * 9 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 12 | * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 13 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 14 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | */ 16 | package bspkrs.mmv; 17 | 18 | import java.util.Comparator; 19 | 20 | import bspkrs.mmv.version.NaturalOrderComparator; 21 | 22 | public class SplittedNaturalComparator implements Comparator 23 | { 24 | private final String splitter; 25 | 26 | public SplittedNaturalComparator(String splitter) 27 | { 28 | this.splitter = splitter; 29 | } 30 | 31 | @Override 32 | public int compare(Object o1, Object o2) 33 | { 34 | String[] a = o1.toString().split(splitter); 35 | String[] b = o2.toString().split(splitter); 36 | 37 | if (a.length != b.length) 38 | return b.length - a.length; 39 | 40 | NaturalOrderComparator comp = new NaturalOrderComparator(); 41 | for (int i = 0; i < a.length; i++) 42 | { 43 | int comparison = comp.compare(a[i], b[i]); 44 | if (comparison != 0) 45 | return comparison; 46 | } 47 | return 0; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/bspkrs/mmv/SrgFile.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Alex "immibis" Campbell, bspkrs 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 5 | * files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 7 | * Software is furnished to do so, subject to the following conditions: 8 | * 9 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 12 | * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 13 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 14 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | * 16 | * Modified version of SrgFile.java from BON 17 | */ 18 | package bspkrs.mmv; 19 | 20 | import java.io.BufferedReader; 21 | import java.io.File; 22 | import java.io.FileReader; 23 | import java.io.IOException; 24 | import java.util.Map; 25 | import java.util.Scanner; 26 | import java.util.Set; 27 | import java.util.TreeMap; 28 | import java.util.TreeSet; 29 | 30 | public class SrgFile 31 | { 32 | // All maps should be inter-connected to reference a single set of objects 33 | public final Map srgClassName2ClassData = new TreeMap(); // full/pkg/ClassSrgName -> ClassSrgData 34 | public final Map> srgPkg2ClassDataSet = new TreeMap>(); // full/pkg -> Set 35 | public final Map srgFieldName2FieldData = new TreeMap(); // field_12345_a -> FieldSrgData 36 | public final Map srgMethodName2MethodData = new TreeMap(); // func_12345_a -> MethodSrgData 37 | public final Map> class2MethodDataSet = new TreeMap>(); 38 | public final Map> class2FieldDataSet = new TreeMap>(); 39 | public final Map srgMethodName2ClassData = new TreeMap(); // func_12345_a -> ClassSrgData 40 | public final Map srgFieldName2ClassData = new TreeMap(); // field_12345_a -> ClassSrgData 41 | 42 | SrgFile() {} // FIXME Needed so that TSrgFile can extend SrgFile. A shared interface/abstract probably makes more sense 43 | 44 | public static String getLastComponent(String s) 45 | { 46 | String[] parts = s.split("/"); 47 | return parts[parts.length - 1]; 48 | } 49 | 50 | public SrgFile(File f, ExcFile excFile, StaticMethodsFile staticMethods) throws IOException 51 | { 52 | Scanner in = new Scanner(new BufferedReader(new FileReader(f))); 53 | try 54 | { 55 | while (in.hasNextLine()) 56 | { 57 | if (in.hasNext("CL:")) 58 | { 59 | // CL: a net/minecraft/util/EnumChatFormatting 60 | in.next(); // skip CL: 61 | String obf = in.next(); 62 | String deobf = in.next(); 63 | String srgName = getLastComponent(deobf); 64 | String pkgName = deobf.substring(0, deobf.lastIndexOf('/')); 65 | 66 | ClassSrgData classData = new ClassSrgData(obf, srgName, pkgName, in.hasNext("#C")); 67 | 68 | if (!srgPkg2ClassDataSet.containsKey(pkgName)) 69 | srgPkg2ClassDataSet.put(pkgName, new TreeSet()); 70 | srgPkg2ClassDataSet.get(pkgName).add(classData); 71 | 72 | srgClassName2ClassData.put(pkgName + "/" + srgName, classData); 73 | 74 | if (!class2MethodDataSet.containsKey(classData)) 75 | class2MethodDataSet.put(classData, new TreeSet()); 76 | 77 | if (!class2FieldDataSet.containsKey(classData)) 78 | class2FieldDataSet.put(classData, new TreeSet()); 79 | } 80 | else if (in.hasNext("FD:")) 81 | { 82 | // FD: aql/c net/minecraft/block/BlockStoneBrick/field_94408_c #C 83 | in.next(); // skip FD: 84 | String[] obf = in.next().split("/"); 85 | String obfOwner = obf[0]; 86 | String obfName = obf[1]; 87 | String deobf = in.next(); 88 | String srgName = getLastComponent(deobf); 89 | String srgPkg = deobf.substring(0, deobf.lastIndexOf('/')); 90 | String srgOwner = getLastComponent(srgPkg); 91 | srgPkg = srgPkg.substring(0, srgPkg.lastIndexOf('/')); 92 | 93 | FieldSrgData fieldData = new FieldSrgData(obfOwner, obfName, srgOwner, srgPkg, srgName, in.hasNext("#C")); 94 | 95 | srgFieldName2FieldData.put(srgName, fieldData); 96 | class2FieldDataSet.get(srgClassName2ClassData.get(srgPkg + "/" + srgOwner)).add(fieldData); 97 | srgFieldName2ClassData.put(srgName, srgClassName2ClassData.get(srgPkg + "/" + srgOwner)); 98 | } 99 | else if (in.hasNext("MD:")) 100 | { 101 | // MD: aor/a (Lmt;)V net/minecraft/block/BlockHay/func_94332_a (Lnet/minecraft/client/renderer/texture/IconRegister;)V #C 102 | in.next(); // skip MD: 103 | String[] obf = in.next().split("/"); 104 | String obfOwner = obf[0]; 105 | String obfName = obf[1]; 106 | String obfDescriptor = in.next(); 107 | String deobf = in.next(); 108 | String srgName = getLastComponent(deobf); 109 | String srgPkg = deobf.substring(0, deobf.lastIndexOf('/')); 110 | String srgOwner = getLastComponent(srgPkg); 111 | srgPkg = srgPkg.substring(0, srgPkg.lastIndexOf('/')); 112 | String srgDescriptor = in.next(); 113 | 114 | MethodSrgData methodData = new MethodSrgData(obfOwner, obfName, obfDescriptor, srgOwner, srgPkg, srgName, srgDescriptor, in.hasNext("#C")); 115 | 116 | srgMethodName2MethodData.put(srgName, methodData); 117 | class2MethodDataSet.get(srgClassName2ClassData.get(srgPkg + "/" + srgOwner)).add(methodData); 118 | srgMethodName2ClassData.put(srgName, srgClassName2ClassData.get(srgPkg + "/" + srgOwner)); 119 | 120 | // Hack in the missing parameter data 121 | ExcData toAdd = new ExcData(srgOwner, srgName, srgDescriptor, new String[0], staticMethods.contains(srgName)); 122 | ExcData existing = excFile.srgMethodName2ExcData.get(srgName); 123 | 124 | if ((existing == null) || (existing.getParameters().length < toAdd.getParameters().length)) 125 | { 126 | excFile.srgMethodName2ExcData.put(srgName, toAdd); 127 | for (String parameter : toAdd.getParameters()) 128 | excFile.srgParamName2ExcData.put(parameter, toAdd); 129 | } 130 | } 131 | else 132 | in.nextLine(); 133 | } 134 | } 135 | finally 136 | { 137 | in.close(); 138 | } 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /src/main/java/bspkrs/mmv/StaticMethodsFile.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 bspkrs 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 5 | * files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 7 | * Software is furnished to do so, subject to the following conditions: 8 | * 9 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 12 | * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 13 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 14 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | */ 16 | package bspkrs.mmv; 17 | 18 | import java.io.BufferedReader; 19 | import java.io.File; 20 | import java.io.FileReader; 21 | import java.io.IOException; 22 | import java.util.ArrayList; 23 | import java.util.List; 24 | import java.util.Scanner; 25 | 26 | public class StaticMethodsFile 27 | { 28 | private final File file; 29 | public List staticMethods; 30 | 31 | public StaticMethodsFile(File file) throws IOException 32 | { 33 | this.file = file; 34 | staticMethods = new ArrayList(); 35 | readFromFile(); 36 | } 37 | 38 | public void readFromFile() throws IOException 39 | { 40 | Scanner in = new Scanner(new BufferedReader(new FileReader(file))); 41 | try 42 | { 43 | while (in.hasNextLine()) 44 | { 45 | staticMethods.add(in.nextLine()); 46 | } 47 | } 48 | finally 49 | { 50 | in.close(); 51 | } 52 | } 53 | 54 | public boolean contains(String srgName) 55 | { 56 | return staticMethods.contains(srgName); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/bspkrs/mmv/TSrgFile.java: -------------------------------------------------------------------------------- 1 | package bspkrs.mmv; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.File; 5 | import java.io.FileNotFoundException; 6 | import java.io.FileReader; 7 | import java.util.*; 8 | 9 | public class TSrgFile extends SrgFile 10 | { 11 | 12 | public TSrgFile(File f, ExcFile excFile, StaticMethodsFile staticMethods) throws FileNotFoundException 13 | { 14 | Scanner in = new Scanner(new BufferedReader(new FileReader(f))); 15 | try 16 | { 17 | String currentPackage = null; 18 | String currentClass = null; 19 | String currentObfClass = null; 20 | while (in.hasNextLine()) 21 | { 22 | String[] line = in.nextLine().split(" "); 23 | 24 | if (line[0].indexOf("\t") == 0) // Member 25 | { 26 | line[0] = line[0].substring(1); // ignore the leading tab 27 | 28 | if (line.length == 2) // Field 29 | { 30 | // a field_192300_a 31 | String obf = line[0]; 32 | String srgName = line[1]; 33 | String obfOwner = currentObfClass; 34 | String srgPkg = currentPackage; 35 | String srgOwner = currentClass; 36 | 37 | FieldSrgData fieldData = new FieldSrgData(obfOwner, obf, srgOwner, srgPkg, srgName, false); 38 | 39 | srgFieldName2FieldData.put(srgName, fieldData); 40 | class2FieldDataSet.get(srgClassName2ClassData.get(srgPkg + "/" + srgOwner)).add(fieldData); 41 | srgFieldName2ClassData.put(srgName, srgClassName2ClassData.get(srgPkg + "/" + srgOwner)); 42 | } 43 | else if (line.length == 3) // Method 44 | { 45 | // b (Lhy;)Lu; func_192295_b 46 | String obf = line[0]; 47 | String descriptor = line[1]; 48 | String srgName = line[2]; 49 | String obfOwner = currentObfClass; 50 | String srgPkg = currentPackage; 51 | String srgOwner = currentClass; 52 | 53 | MethodSrgData methodData = new MethodSrgData(obfOwner, obf, descriptor, srgOwner, srgPkg, srgName, descriptor/*FIXME*/, false); 54 | 55 | srgMethodName2MethodData.put(srgName, methodData); 56 | class2MethodDataSet.get(srgClassName2ClassData.get(srgPkg + "/" + srgOwner)).add(methodData); 57 | srgMethodName2ClassData.put(srgName, srgClassName2ClassData.get(srgPkg + "/" + srgOwner)); 58 | 59 | // Hack in the missing parameter data 60 | ExcData toAdd = new ExcData(srgOwner, srgName, descriptor/*FIXME*/, new String[0], staticMethods.contains(srgName)); 61 | ExcData existing = excFile.srgMethodName2ExcData.get(srgName); 62 | 63 | if ((existing == null) || (existing.getParameters().length < toAdd.getParameters().length)) 64 | { 65 | excFile.srgMethodName2ExcData.put(srgName, toAdd); 66 | for (String parameter : toAdd.getParameters()) 67 | excFile.srgParamName2ExcData.put(parameter, toAdd); 68 | } 69 | } 70 | } 71 | else // Class 72 | { 73 | // u net/minecraft/advancements/DisplayInfo 74 | currentObfClass = line[0]; 75 | currentPackage = line[1].substring(0, line[1].lastIndexOf('/')); 76 | currentClass = line[1].substring(line[1].lastIndexOf('/') + 1); 77 | 78 | ClassSrgData classData = new ClassSrgData(currentObfClass, currentClass, currentPackage, false); 79 | 80 | if (!srgPkg2ClassDataSet.containsKey(currentPackage)) 81 | srgPkg2ClassDataSet.put(currentPackage, new TreeSet()); 82 | srgPkg2ClassDataSet.get(currentPackage).add(classData); 83 | 84 | srgClassName2ClassData.put(currentPackage + "/" + currentClass, classData); 85 | 86 | if (!class2MethodDataSet.containsKey(classData)) 87 | class2MethodDataSet.put(classData, new TreeSet()); 88 | 89 | if (!class2FieldDataSet.containsKey(classData)) 90 | class2FieldDataSet.put(classData, new TreeSet()); 91 | } 92 | } 93 | } 94 | finally 95 | { 96 | in.close(); 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/main/java/bspkrs/mmv/VersionFetcher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 bspkrs 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 5 | * files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 7 | * Software is furnished to do so, subject to the following conditions: 8 | * 9 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 12 | * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 13 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 14 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | */ 16 | package bspkrs.mmv; 17 | 18 | import java.io.BufferedReader; 19 | import java.io.IOException; 20 | import java.io.InputStreamReader; 21 | import java.net.URL; 22 | import java.net.URLConnection; 23 | import java.util.ArrayList; 24 | import java.util.Collections; 25 | import java.util.List; 26 | import java.util.Map; 27 | 28 | import com.google.gson.Gson; 29 | 30 | public class VersionFetcher 31 | { 32 | private final String jsonUrl = "https://maven.minecraftforge.net/de/oceanlabs/mcp/versions.json"; 33 | private List versions; 34 | 35 | @SuppressWarnings("unchecked") 36 | public List getVersions(boolean force) throws IOException 37 | { 38 | if ((versions == null) || force) 39 | { 40 | final URL url = new URL(jsonUrl); 41 | final URLConnection connection = url.openConnection(); 42 | connection.addRequestProperty("User-Agent", "MMV/1.0.0"); 43 | BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream())); 44 | 45 | Map json = new Gson().fromJson(br, Map.class); 46 | 47 | versions = new ArrayList(); 48 | for (String mcVer : json.keySet()) 49 | for (String channel : ((Map[]>) json.get(mcVer)).keySet()) 50 | for (Double ver : ((Map>) json.get(mcVer)).get(channel)) 51 | versions.add(mcVer + "_" + channel + "_" + String.format("%.0f", ver)); 52 | Collections.sort(versions, Collections.reverseOrder(new SplittedNaturalComparator("_"))); 53 | return versions; 54 | } 55 | else 56 | return versions; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/bspkrs/mmv/gui/BrowseActionListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Alex "immibis" Campbell, bspkrs 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 5 | * files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 7 | * Software is furnished to do so, subject to the following conditions: 8 | * 9 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 12 | * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 13 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 14 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | */ 16 | package bspkrs.mmv.gui; 17 | 18 | import immibis.bon.gui.Reference; 19 | 20 | import java.awt.Component; 21 | import java.awt.event.ActionEvent; 22 | import java.awt.event.ActionListener; 23 | import java.io.File; 24 | import java.io.IOException; 25 | 26 | import javax.swing.DefaultComboBoxModel; 27 | import javax.swing.JComboBox; 28 | import javax.swing.JFileChooser; 29 | import javax.swing.filechooser.FileFilter; 30 | 31 | public class BrowseActionListener implements ActionListener 32 | { 33 | 34 | private JComboBox comboBox; 35 | private boolean isOpen; 36 | private Component parent; 37 | private JFileChooser jfc; 38 | private Reference defaultDir; 39 | 40 | public BrowseActionListener(JComboBox inputField, boolean isOpen, Component parent, boolean dirOnly, Reference defaultDir) 41 | { 42 | 43 | this.defaultDir = defaultDir; 44 | this.comboBox = inputField; 45 | this.isOpen = isOpen; 46 | this.parent = parent; 47 | 48 | jfc = new JFileChooser(); 49 | jfc.setFileSelectionMode(dirOnly ? JFileChooser.DIRECTORIES_ONLY : JFileChooser.FILES_ONLY); 50 | 51 | if (!dirOnly) 52 | jfc.addChoosableFileFilter(new FileFilter() 53 | { 54 | @Override 55 | public String getDescription() 56 | { 57 | return "Jars and zips only"; 58 | } 59 | 60 | @Override 61 | public boolean accept(File arg0) 62 | { 63 | String fn = arg0.getName(); 64 | return arg0.isDirectory() || fn.endsWith(".jar") || fn.endsWith(".zip"); 65 | } 66 | }); 67 | } 68 | 69 | @Override 70 | public void actionPerformed(ActionEvent arg0) 71 | { 72 | int rv; 73 | jfc.setCurrentDirectory(defaultDir.val); 74 | if (isOpen) 75 | rv = jfc.showOpenDialog(parent); 76 | else 77 | rv = jfc.showSaveDialog(parent); 78 | 79 | if (rv == JFileChooser.APPROVE_OPTION) 80 | { 81 | File f = jfc.getSelectedFile(); 82 | 83 | String path; 84 | try 85 | { 86 | path = f.getCanonicalPath(); 87 | 88 | } 89 | catch (IOException e) 90 | { 91 | path = f.getAbsolutePath(); 92 | } 93 | 94 | DefaultComboBoxModel model = (DefaultComboBoxModel) comboBox.getModel(); 95 | 96 | if (model.getIndexOf(path) != -1) 97 | model.removeElement(path); 98 | 99 | comboBox.insertItemAt(path, 0); 100 | comboBox.setSelectedItem(path); 101 | } 102 | 103 | defaultDir.val = new File((String) comboBox.getSelectedItem()); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/main/java/bspkrs/mmv/gui/MappingGui.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 bspkrs 3 | * Portions Copyright (C) 2014 Alex "immibis" Campbell 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 6 | * files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, 7 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 8 | * Software is furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | * 12 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 13 | * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 15 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 16 | */ 17 | package bspkrs.mmv.gui; 18 | 19 | import java.awt.BorderLayout; 20 | import java.awt.Color; 21 | import java.awt.Component; 22 | import java.awt.Cursor; 23 | import java.awt.Desktop; 24 | import java.awt.Dimension; 25 | import java.awt.EventQueue; 26 | import java.awt.FlowLayout; 27 | import java.awt.Font; 28 | import java.awt.Toolkit; 29 | import java.awt.datatransfer.StringSelection; 30 | import java.awt.event.ActionEvent; 31 | import java.awt.event.ActionListener; 32 | import java.awt.event.FocusAdapter; 33 | import java.awt.event.FocusEvent; 34 | import java.awt.event.ItemEvent; 35 | import java.awt.event.ItemListener; 36 | import java.awt.event.KeyAdapter; 37 | import java.awt.event.KeyEvent; 38 | import java.awt.event.MouseAdapter; 39 | import java.awt.event.MouseEvent; 40 | import java.awt.event.WindowAdapter; 41 | import java.awt.event.WindowEvent; 42 | import java.io.IOException; 43 | import java.text.SimpleDateFormat; 44 | import java.util.ArrayList; 45 | import java.util.Arrays; 46 | import java.util.Collections; 47 | import java.util.Date; 48 | import java.util.HashMap; 49 | import java.util.HashSet; 50 | import java.util.List; 51 | import java.util.Map; 52 | import java.util.Set; 53 | import java.util.prefs.Preferences; 54 | 55 | import javax.swing.DefaultComboBoxModel; 56 | import javax.swing.ImageIcon; 57 | import javax.swing.JButton; 58 | import javax.swing.JCheckBox; 59 | import javax.swing.JComboBox; 60 | import javax.swing.JEditorPane; 61 | import javax.swing.JFrame; 62 | import javax.swing.JLabel; 63 | import javax.swing.JOptionPane; 64 | import javax.swing.JPanel; 65 | import javax.swing.JProgressBar; 66 | import javax.swing.JScrollPane; 67 | import javax.swing.JSeparator; 68 | import javax.swing.JSplitPane; 69 | import javax.swing.JTable; 70 | import javax.swing.ListSelectionModel; 71 | import javax.swing.RowSorter; 72 | import javax.swing.ScrollPaneConstants; 73 | import javax.swing.SortOrder; 74 | import javax.swing.SwingConstants; 75 | import javax.swing.SwingUtilities; 76 | import javax.swing.UIManager; 77 | import javax.swing.event.HyperlinkEvent; 78 | import javax.swing.event.HyperlinkListener; 79 | import javax.swing.event.ListSelectionEvent; 80 | import javax.swing.event.ListSelectionListener; 81 | import javax.swing.table.DefaultTableModel; 82 | 83 | import bspkrs.mmv.McpMappingLoader; 84 | import bspkrs.mmv.McpMappingLoader.CantLoadMCPMappingException; 85 | import bspkrs.mmv.VersionFetcher; 86 | import bspkrs.mmv.version.AppVersionChecker; 87 | import immibis.bon.IProgressListener; 88 | 89 | public class MappingGui extends JFrame 90 | { 91 | public static final String VERSION_NUMBER = "1.0.1"; 92 | private static final long serialVersionUID = 1L; 93 | private final Preferences prefs = Preferences.userNodeForPackage(MappingGui.class); 94 | private JFrame frmMcpMappingViewer; 95 | private JButton btnRefreshTables; 96 | private JComboBox cmbMappingVersion; 97 | private JCheckBox chkForceRefresh; 98 | private JPanel pnlProgress; 99 | private JProgressBar progressBar; 100 | private JPanel pnlFilter; 101 | private JComboBox cmbFilter; 102 | private JButton btnSearch; 103 | private JButton btnGetBotCommands; 104 | private JCheckBox chkClearOnCopy; 105 | private final static String PREFS_KEY_FILTER = "filter"; 106 | private final static String PREFS_KEY_CLASS_SORT = "classSort"; 107 | private final static String PREFS_KEY_METHOD_SORT = "methodSort"; 108 | private final static String PREFS_KEY_PARAM_SORT = "paramSort"; 109 | private final static String PREFS_KEY_FIELD_SORT = "fieldSort"; 110 | private final List classSort = new ArrayList(); 111 | private final List methodSort = new ArrayList(); 112 | private final List paramSort = new ArrayList(); 113 | private final List fieldSort = new ArrayList(); 114 | private JTable tblClasses; 115 | private JTable tblMethods; 116 | private JTable tblFields; 117 | private JTable tblParams; 118 | private Thread curTask = null; 119 | private final Map mcpInstances = new HashMap<>(); 120 | private final VersionFetcher versionFetcher = new VersionFetcher(); 121 | private McpMappingLoader currentLoader; 122 | private AppVersionChecker versionChecker; 123 | private final String versionURL = "http://bspk.rs/Minecraft/MMV/MMV.version"; 124 | private final String mcfTopic = "http://www.minecraftforum.net/topic/2115030-"; 125 | 126 | // @formatter:off 127 | public static DefaultTableModel classesDefaultModel = new DefaultTableModel(new Object[][] { {}, }, new String[] { "Pkg name", "SRG name", "Obf name" }) 128 | { 129 | private static final long serialVersionUID = 1L; 130 | boolean[] columnEditables = new boolean[] { false, false, false }; 131 | @SuppressWarnings("rawtypes") 132 | Class[] columnTypes = new Class[] { String.class, String.class, String.class }; 133 | 134 | @SuppressWarnings({ "unchecked", "rawtypes" }) 135 | @Override 136 | public Class getColumnClass(int columnIndex) { return columnTypes[columnIndex]; } 137 | 138 | @Override 139 | public boolean isCellEditable(int row, int column) { return columnEditables[column]; } 140 | }; 141 | 142 | public static DefaultTableModel methodsDefaultModel = new DefaultTableModel( new Object[][] { {}, }, new String[] { "MCP Name", "SRG Name", "Obf Name", "SRG Descriptor", "Comment" }) 143 | { 144 | private static final long serialVersionUID = 1L; 145 | boolean[] columnEditables = new boolean[] { false, false, false, false, false }; 146 | @SuppressWarnings("rawtypes") 147 | Class[] columnTypes = new Class[] { String.class, String.class, String.class, String.class, String.class }; 148 | 149 | @SuppressWarnings({ "unchecked", "rawtypes" }) 150 | @Override 151 | public Class getColumnClass(int columnIndex) { return columnTypes[columnIndex]; } 152 | 153 | @Override 154 | public boolean isCellEditable(int row, int column) { return columnEditables[column]; } 155 | }; 156 | 157 | public static DefaultTableModel paramsDefaultModel = new DefaultTableModel( new Object[][] { {}, }, new String[] { "MCP Name", "SRG Name", "Type" }) 158 | { 159 | private static final long serialVersionUID = 1L; 160 | boolean[] columnEditables = new boolean[] { false, false, false }; 161 | @SuppressWarnings("rawtypes") 162 | Class[] columnTypes = new Class[] { String.class, String.class, String.class }; 163 | 164 | @SuppressWarnings({ "unchecked", "rawtypes" }) 165 | @Override 166 | public Class getColumnClass(int columnIndex) { return columnTypes[columnIndex]; } 167 | 168 | @Override 169 | public boolean isCellEditable(int row, int column) { return columnEditables[column]; } 170 | }; 171 | 172 | public static DefaultTableModel fieldsDefaultModel = new DefaultTableModel( new Object[][] { {}, }, new String[] { "MCP Name", "SRG Name", "Obf Name", "Comment" } ) 173 | { 174 | private static final long serialVersionUID = 1L; 175 | boolean[] columnEditables = new boolean[] { false, false, false, false }; 176 | @SuppressWarnings("rawtypes") 177 | Class[] columnTypes = new Class[] { String.class, String.class, String.class, String.class }; 178 | 179 | @SuppressWarnings({ "unchecked", "rawtypes" }) 180 | @Override 181 | public Class getColumnClass(int columnIndex) { return columnTypes[columnIndex]; } 182 | 183 | @Override 184 | public boolean isCellEditable(int row, int column) { return columnEditables[column]; } 185 | }; 186 | private JSplitPane splitMethods; 187 | private JButton btnGetVersions; 188 | // @formatter:on 189 | 190 | private void savePrefs() 191 | { 192 | for (int i = 0; i < Math.min(cmbFilter.getItemCount(), 20); i++) 193 | prefs.put(PREFS_KEY_FILTER + i, cmbFilter.getItemAt(i)); 194 | 195 | if (tblClasses.getRowSorter().getSortKeys().size() > 0) 196 | { 197 | int i = tblClasses.getRowSorter().getSortKeys().get(0).getColumn() + 1; 198 | SortOrder order = tblClasses.getRowSorter().getSortKeys().get(0).getSortOrder(); 199 | prefs.putInt(PREFS_KEY_CLASS_SORT, order == SortOrder.DESCENDING ? i * -1 : i); 200 | } 201 | else 202 | prefs.putInt(PREFS_KEY_CLASS_SORT, 1); 203 | 204 | if (tblMethods.getRowSorter().getSortKeys().size() > 0) 205 | { 206 | int i = tblMethods.getRowSorter().getSortKeys().get(0).getColumn() + 1; 207 | SortOrder order = tblMethods.getRowSorter().getSortKeys().get(0).getSortOrder(); 208 | prefs.putInt(PREFS_KEY_METHOD_SORT, order == SortOrder.DESCENDING ? i * -1 : i); 209 | } 210 | else 211 | prefs.putInt(PREFS_KEY_METHOD_SORT, 1); 212 | 213 | if (tblParams.getRowSorter().getSortKeys().size() > 0) 214 | { 215 | int i = tblParams.getRowSorter().getSortKeys().get(0).getColumn() + 1; 216 | SortOrder order = tblParams.getRowSorter().getSortKeys().get(0).getSortOrder(); 217 | prefs.putInt(PREFS_KEY_PARAM_SORT, order == SortOrder.DESCENDING ? i * -1 : i); 218 | } 219 | else 220 | prefs.putInt(PREFS_KEY_PARAM_SORT, 1); 221 | 222 | if (tblFields.getRowSorter().getSortKeys().size() > 0) 223 | { 224 | int i = tblFields.getRowSorter().getSortKeys().get(0).getColumn() + 1; 225 | SortOrder order = tblFields.getRowSorter().getSortKeys().get(0).getSortOrder(); 226 | prefs.putInt(PREFS_KEY_FIELD_SORT, order == SortOrder.DESCENDING ? i * -1 : i); 227 | } 228 | else 229 | prefs.putInt(PREFS_KEY_FIELD_SORT, 1); 230 | } 231 | 232 | private void loadPrefs(boolean sortOnly) 233 | { 234 | if (!sortOnly) 235 | { 236 | DefaultComboBoxModel model = (DefaultComboBoxModel) cmbFilter.getModel(); 237 | for (int i = 0; i < 20; i++) 238 | { 239 | String item = prefs.get(PREFS_KEY_FILTER + i, " "); 240 | if (!item.equals(" ")) 241 | { 242 | if (model.getIndexOf(item) == -1) 243 | cmbFilter.addItem(item); 244 | } 245 | } 246 | 247 | cmbFilter.setSelectedIndex(-1); 248 | 249 | if (cmbMappingVersion.getItemCount() > 0) 250 | { 251 | btnRefreshTables.setEnabled(true); 252 | cmbMappingVersion.setSelectedIndex(0); 253 | } 254 | else 255 | btnRefreshTables.setEnabled(false); 256 | } 257 | 258 | classSort.clear(); 259 | methodSort.clear(); 260 | paramSort.clear(); 261 | fieldSort.clear(); 262 | 263 | int i = prefs.getInt(PREFS_KEY_CLASS_SORT, 1); 264 | classSort.add(new RowSorter.SortKey(Math.abs(i) - 1, i > 0 ? SortOrder.ASCENDING : SortOrder.DESCENDING)); 265 | tblClasses.getRowSorter().setSortKeys(classSort); 266 | 267 | i = prefs.getInt(PREFS_KEY_METHOD_SORT, 1); 268 | methodSort.add(new RowSorter.SortKey(Math.abs(i) - 1, i > 0 ? SortOrder.ASCENDING : SortOrder.DESCENDING)); 269 | tblMethods.getRowSorter().setSortKeys(methodSort); 270 | 271 | i = prefs.getInt(PREFS_KEY_PARAM_SORT, 1); 272 | paramSort.add(new RowSorter.SortKey(Math.abs(i) - 1, i > 0 ? SortOrder.ASCENDING : SortOrder.DESCENDING)); 273 | tblParams.getRowSorter().setSortKeys(paramSort); 274 | 275 | i = prefs.getInt(PREFS_KEY_FIELD_SORT, 1); 276 | fieldSort.add(new RowSorter.SortKey(Math.abs(i) - 1, i > 0 ? SortOrder.ASCENDING : SortOrder.DESCENDING)); 277 | tblFields.getRowSorter().setSortKeys(fieldSort); 278 | } 279 | 280 | private void checkForUpdates() 281 | { 282 | versionChecker = new AppVersionChecker("MCP Mapping Viewer", VERSION_NUMBER, versionURL, mcfTopic, 283 | new String[] { "{appName} {oldVer} is out of date! Visit {updateURL} to download the latest release ({newVer})." }, 284 | new String[] { 285 | "{appName} {oldVer} is out of date!

Download the latest release ({newVer}) from {updateURL}." }, 286 | 5000); 287 | if (!versionChecker.isCurrentVersion()) 288 | { 289 | showHTMLDialog(MappingGui.this, versionChecker.getDialogMessage()[0], "An update is available", JOptionPane.INFORMATION_MESSAGE); 290 | } 291 | } 292 | 293 | /** 294 | * Launch the application. 295 | */ 296 | public static void main(String[] args) 297 | { 298 | try 299 | { 300 | // Set System L&F 301 | UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 302 | } 303 | catch (Throwable e) 304 | {} 305 | EventQueue.invokeLater(new Runnable() 306 | { 307 | @Override 308 | public void run() 309 | { 310 | try 311 | { 312 | MappingGui window = new MappingGui(); 313 | window.frmMcpMappingViewer.setVisible(true); 314 | } 315 | catch (Exception e) 316 | { 317 | e.printStackTrace(); 318 | } 319 | } 320 | }); 321 | } 322 | 323 | private static String getPrintableStackTrace(Throwable e, Set stopAt) 324 | { 325 | String s = e.toString(); 326 | int numPrinted = 0; 327 | for (StackTraceElement ste : e.getStackTrace()) 328 | { 329 | boolean stopHere = false; 330 | if (stopAt.contains(ste) && numPrinted > 0) 331 | stopHere = true; 332 | else 333 | { 334 | s += "\n at " + ste.toString(); 335 | numPrinted++; 336 | if (ste.getClassName().startsWith("javax.swing.")) 337 | stopHere = true; 338 | } 339 | 340 | if (stopHere) 341 | { 342 | int numHidden = e.getStackTrace().length - numPrinted; 343 | s += "\n ... " + numHidden + " more"; 344 | break; 345 | } 346 | } 347 | return s; 348 | } 349 | 350 | private static String getStackTraceMessage(String prefix, Throwable e) 351 | { 352 | String s = prefix; 353 | 354 | s += "\n" + getPrintableStackTrace(e, Collections. emptySet()); 355 | while (e.getCause() != null) 356 | { 357 | Set stopAt = new HashSet(Arrays.asList(e.getStackTrace())); 358 | e = e.getCause(); 359 | s += "\nCaused by: " + getPrintableStackTrace(e, stopAt); 360 | } 361 | return s; 362 | } 363 | 364 | /** 365 | * Create the application. 366 | */ 367 | public MappingGui() 368 | { 369 | initialize(); 370 | checkForUpdates(); 371 | } 372 | 373 | public void setCsvFileEdited(boolean bol) 374 | { 375 | btnGetBotCommands.setEnabled(bol); 376 | } 377 | 378 | /** 379 | * Initialize the contents of the frame. 380 | */ 381 | private void initialize() 382 | { 383 | frmMcpMappingViewer = new JFrame(); 384 | frmMcpMappingViewer.setIconImage(new ImageIcon(MappingGui.class.getResource("/bspkrs/mmv/gui/icon/bspkrs32.png")).getImage()); 385 | frmMcpMappingViewer.addWindowListener(new WindowAdapter() 386 | { 387 | @Override 388 | public void windowClosing(WindowEvent arg0) 389 | { 390 | savePrefs(); 391 | } 392 | }); 393 | frmMcpMappingViewer.setTitle("MCP Mapping Viewer"); 394 | frmMcpMappingViewer.setBounds(100, 100, 925, 621); 395 | frmMcpMappingViewer.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 396 | frmMcpMappingViewer.getContentPane().setLayout(new BorderLayout(0, 0)); 397 | 398 | JSplitPane splitMain = new JSplitPane(); 399 | splitMain.setBorder(null); 400 | splitMain.setDividerSize(3); 401 | splitMain.setResizeWeight(0.5); 402 | splitMain.setContinuousLayout(true); 403 | splitMain.setMinimumSize(new Dimension(179, 80)); 404 | splitMain.setPreferredSize(new Dimension(179, 80)); 405 | splitMain.setOrientation(JSplitPane.VERTICAL_SPLIT); 406 | 407 | JScrollPane scrlpnClasses = new JScrollPane(); 408 | scrlpnClasses.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); 409 | splitMain.setLeftComponent(scrlpnClasses); 410 | 411 | tblClasses = new JTable(); 412 | tblClasses.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); 413 | scrlpnClasses.setViewportView(tblClasses); 414 | tblClasses.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 415 | tblClasses.getSelectionModel().addListSelectionListener(new ClassTableSelectionListener(tblClasses)); 416 | tblClasses.setAutoCreateRowSorter(true); 417 | tblClasses.setEnabled(false); 418 | tblClasses.setModel(classesDefaultModel); 419 | tblClasses.setFillsViewportHeight(true); 420 | tblClasses.setCellSelectionEnabled(true); 421 | frmMcpMappingViewer.getContentPane().add(splitMain, BorderLayout.CENTER); 422 | 423 | JSplitPane splitMembers = new JSplitPane(); 424 | splitMembers.setBorder(null); 425 | splitMembers.setDividerSize(3); 426 | splitMembers.setResizeWeight(0.5); 427 | splitMembers.setOrientation(JSplitPane.VERTICAL_SPLIT); 428 | splitMain.setRightComponent(splitMembers); 429 | 430 | splitMethods = new JSplitPane(); 431 | splitMethods.setBorder(null); 432 | splitMethods.setDividerSize(3); 433 | splitMethods.setResizeWeight(0.5); 434 | splitMembers.setLeftComponent(splitMethods); 435 | 436 | JScrollPane scrlpnMethods = new JScrollPane(); 437 | scrlpnMethods.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); 438 | splitMethods.setLeftComponent(scrlpnMethods); 439 | 440 | tblMethods = new JTable(); 441 | tblMethods.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); 442 | tblMethods.getSelectionModel().addListSelectionListener(new MethodTableSelectionListener(tblMethods)); 443 | tblMethods.setCellSelectionEnabled(true); 444 | tblMethods.setFillsViewportHeight(true); 445 | tblMethods.setAutoCreateRowSorter(true); 446 | tblMethods.setEnabled(false); 447 | tblMethods.setModel(methodsDefaultModel); 448 | scrlpnMethods.setViewportView(tblMethods); 449 | 450 | JScrollPane scrlpnParams = new JScrollPane(); 451 | scrlpnParams.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); 452 | splitMethods.setRightComponent(scrlpnParams); 453 | 454 | tblParams = new JTable(); 455 | tblParams.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); 456 | tblParams.setCellSelectionEnabled(true); 457 | tblParams.setFillsViewportHeight(true); 458 | tblParams.setAutoCreateRowSorter(true); 459 | tblParams.setEnabled(false); 460 | tblParams.setModel(paramsDefaultModel); 461 | scrlpnParams.setViewportView(tblParams); 462 | 463 | SwingUtilities.invokeLater(new Runnable() 464 | { 465 | @Override 466 | public void run() 467 | { 468 | splitMethods.setDividerLocation(0.8); 469 | } 470 | }); 471 | 472 | JScrollPane scrlpnFields = new JScrollPane(); 473 | scrlpnFields.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); 474 | splitMembers.setRightComponent(scrlpnFields); 475 | 476 | tblFields = new JTable(); 477 | tblFields.setCellSelectionEnabled(true); 478 | tblFields.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); 479 | tblFields.setAutoCreateRowSorter(true); 480 | tblFields.setEnabled(false); 481 | tblFields.setModel(fieldsDefaultModel); 482 | tblFields.setFillsViewportHeight(true); 483 | scrlpnFields.setViewportView(tblFields); 484 | 485 | JPanel pnlHeader = new JPanel(); 486 | frmMcpMappingViewer.getContentPane().add(pnlHeader, BorderLayout.NORTH); 487 | pnlHeader.setLayout(new BorderLayout(0, 0)); 488 | 489 | JPanel pnlControls = new JPanel(); 490 | pnlHeader.add(pnlControls, BorderLayout.NORTH); 491 | pnlControls.setSize(new Dimension(0, 40)); 492 | pnlControls.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 2)); 493 | 494 | cmbMappingVersion = new JComboBox(new DefaultComboBoxModel()); 495 | cmbMappingVersion.setEditable(false); 496 | cmbMappingVersion.setPreferredSize(new Dimension(320, 20)); 497 | cmbMappingVersion.addItemListener(new MappingVersionsComboItemChanged()); 498 | 499 | JLabel lblMappingVersion = new JLabel("Mapping Version"); 500 | pnlControls.add(lblMappingVersion); 501 | pnlControls.add(cmbMappingVersion); 502 | 503 | btnGetVersions = new JButton("Get Versions"); 504 | btnGetVersions.addActionListener(new ActionListener() 505 | { 506 | @Override 507 | public void actionPerformed(ActionEvent e) 508 | { 509 | try 510 | { 511 | cmbMappingVersion.removeAllItems(); 512 | for (String s : versionFetcher.getVersions(chkForceRefresh.isSelected())) 513 | { 514 | cmbMappingVersion.addItem(s); 515 | } 516 | } 517 | catch (IOException exc) 518 | {} 519 | } 520 | }); 521 | pnlControls.add(btnGetVersions); 522 | 523 | btnRefreshTables = new JButton("Load Mappings"); 524 | btnRefreshTables.setEnabled(false); 525 | btnRefreshTables.addActionListener(new RefreshActionListener()); 526 | pnlControls.add(btnRefreshTables); 527 | 528 | chkForceRefresh = new JCheckBox("Force reload"); 529 | chkForceRefresh.setToolTipText("Force a reload from the MCP conf folder files instead of the session cache."); 530 | pnlControls.add(chkForceRefresh); 531 | 532 | pnlProgress = new JPanel(); 533 | pnlProgress.setVisible(false); 534 | pnlHeader.add(pnlProgress, BorderLayout.SOUTH); 535 | pnlProgress.setLayout(new BorderLayout(0, 0)); 536 | 537 | progressBar = new JProgressBar(); 538 | progressBar.setStringPainted(true); 539 | progressBar.setString(""); 540 | progressBar.setForeground(UIManager.getColor("ProgressBar.foreground")); 541 | pnlProgress.add(progressBar); 542 | 543 | pnlFilter = new JPanel(); 544 | FlowLayout flowLayout = (FlowLayout) pnlFilter.getLayout(); 545 | flowLayout.setVgap(2); 546 | flowLayout.setAlignment(FlowLayout.LEFT); 547 | pnlFilter.setVisible(true); 548 | pnlHeader.add(pnlFilter, BorderLayout.CENTER); 549 | 550 | JLabel lblFilter = new JLabel("Search"); 551 | pnlFilter.add(lblFilter); 552 | 553 | cmbFilter = new JComboBox(); 554 | cmbFilter.setEditable(true); 555 | cmbFilter.setPreferredSize(new Dimension(300, 20)); 556 | cmbFilter.setMaximumRowCount(10); 557 | pnlFilter.add(cmbFilter); 558 | 559 | btnSearch = new JButton("Go"); 560 | btnSearch.setToolTipText(""); 561 | btnSearch.addActionListener(new SearchActionListener()); 562 | pnlFilter.add(btnSearch); 563 | cmbFilter.setEnabled(false); 564 | cmbFilter.addActionListener(new FilterComboTextEdited()); 565 | cmbFilter.getEditor().getEditorComponent().addFocusListener(new FocusAdapter() 566 | { 567 | @Override 568 | public void focusGained(FocusEvent e) 569 | { 570 | cmbFilter.getEditor().selectAll(); 571 | } 572 | }); 573 | cmbFilter.getEditor().getEditorComponent().addKeyListener(new KeyAdapter() 574 | { 575 | @Override 576 | public void keyReleased(KeyEvent e) 577 | { 578 | if (e.getKeyCode() == KeyEvent.VK_ENTER) 579 | btnSearch.doClick(); 580 | } 581 | }); 582 | btnSearch.setEnabled(false); 583 | 584 | JLabel lblSearchInfo = new JLabel("A note on search"); 585 | lblSearchInfo.addMouseListener(new MouseAdapter() 586 | { 587 | @Override 588 | public void mouseClicked(MouseEvent e) 589 | { 590 | String message = "Search is global and returns a set of classes that contain a match for the input. \n" + 591 | "Search is case sensitive!\n\nData elements searched on:\n" + 592 | "Classes:\n ~ Pkg Name\n ~ SRG Name\n ~ Obf Name\n" + 593 | "Methods/Fields:\n ~ SRG Name\n ~ Obf Name\n ~ MCP Name\n ~ Comment\n\n" + 594 | "Parameters are not currently searchable."; 595 | JOptionPane.showMessageDialog(MappingGui.this, message, "Search Info", JOptionPane.INFORMATION_MESSAGE); 596 | } 597 | }); 598 | lblSearchInfo.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); 599 | lblSearchInfo.setForeground(Color.BLUE); 600 | pnlFilter.add(lblSearchInfo); 601 | 602 | JSeparator separator = new JSeparator(); 603 | separator.setPreferredSize(new Dimension(1, 12)); 604 | separator.setOrientation(SwingConstants.VERTICAL); 605 | pnlFilter.add(separator); 606 | 607 | JLabel lblAbout = new JLabel("About"); 608 | pnlFilter.add(lblAbout); 609 | lblAbout.setForeground(Color.BLUE); 610 | lblAbout.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); 611 | 612 | JSeparator separator_1 = new JSeparator(); 613 | separator_1.setPreferredSize(new Dimension(1, 12)); 614 | separator_1.setOrientation(SwingConstants.VERTICAL); 615 | pnlFilter.add(separator_1); 616 | 617 | btnGetBotCommands = new JButton("Get Command List"); 618 | btnGetBotCommands.setToolTipText("Exports to the system clipboard a listing of MCPBot commands for any edits you have made in the GUI."); 619 | btnGetBotCommands.setEnabled(false); 620 | btnGetBotCommands.addActionListener(new ActionListener() 621 | { 622 | @Override 623 | public void actionPerformed(ActionEvent e) 624 | { 625 | String commands = currentLoader.getBotCommands(chkClearOnCopy.isSelected()); 626 | if (commands != null && !commands.isEmpty()) 627 | { 628 | Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(commands), null); 629 | JOptionPane.showMessageDialog(MappingGui.this, "Commands copied to clipboard: \n" + commands, "MMV - MCPBot Commands", 630 | JOptionPane.INFORMATION_MESSAGE); 631 | 632 | if (chkClearOnCopy.isSelected()) 633 | btnGetBotCommands.setEnabled(false); 634 | } 635 | else 636 | JOptionPane.showMessageDialog(MappingGui.this, "No commands to copy.", "MMV - MCPBot Commands", JOptionPane.INFORMATION_MESSAGE); 637 | 638 | chkClearOnCopy.setSelected(false); 639 | } 640 | }); 641 | pnlFilter.add(btnGetBotCommands); 642 | 643 | chkClearOnCopy = new JCheckBox("Clear"); 644 | chkClearOnCopy.setToolTipText("Whether or not to clear the MCPBot command list when the button is clicked."); 645 | pnlFilter.add(chkClearOnCopy); 646 | 647 | lblAbout.addMouseListener(new MouseAdapter() 648 | { 649 | @Override 650 | public void mouseClicked(MouseEvent e) 651 | { 652 | MappingGui.class.getClassLoader(); 653 | String imgsrc = MappingGui.class.getResource("/bspkrs/mmv/gui/icon/bspkrs.png").toString(); 654 | String year = new SimpleDateFormat("yyyy").format(new Date()); 655 | String message = "

" + 656 | "MCP Mapping Viewer v" + VERSION_NUMBER + "
" + 657 | "Copyright (C) 2013-" + year + " bspkrs
" + 658 | "Portions Copyright (C) 2013 Alex \"immibis\" Campbell

" + 659 | "Author: bspkrs
" + 660 | "Credits: immibis (for BON code), " + 661 | "Searge et al (for MCP)

" + 662 | "MCF Thread
" + 663 | "Github Repo
" + 664 | "Change Log
" + 665 | "Binary Downloads
" + 666 | "License
" + 667 | "GSON License
" + 668 | "bspkrs on Twitter
"; 669 | showHTMLDialog(MappingGui.this, message, "About MCP Mapping Viewer", JOptionPane.PLAIN_MESSAGE); 670 | } 671 | }); 672 | 673 | addWindowListener(new WindowAdapter() 674 | { 675 | @Override 676 | public void windowClosing(WindowEvent e) 677 | { 678 | savePrefs(); 679 | } 680 | }); 681 | 682 | try 683 | { 684 | loadPrefs(false); 685 | } 686 | catch (Throwable e) 687 | { 688 | String s = getStackTraceMessage( 689 | "An error has occurred - give bspkrs this stack trace (which has been copied to the clipboard) if the error continues to occur on launch.\n", 690 | e); 691 | 692 | System.err.println(s); 693 | 694 | final String errMsg = s; 695 | SwingUtilities.invokeLater(new Runnable() 696 | { 697 | @Override 698 | public void run() 699 | { 700 | progressBar.setString(" "); 701 | progressBar.setValue(0); 702 | 703 | Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(errMsg), null); 704 | JOptionPane.showMessageDialog(MappingGui.this, errMsg, "MMV - Error", JOptionPane.ERROR_MESSAGE); 705 | } 706 | }); 707 | } 708 | } 709 | 710 | class MappingVersionsComboItemChanged implements ItemListener 711 | { 712 | @Override 713 | public void itemStateChanged(ItemEvent e) 714 | { 715 | if (e.getStateChange() == ItemEvent.SELECTED) 716 | { 717 | @SuppressWarnings("unchecked") 718 | JComboBox cmb = (JComboBox) e.getSource(); 719 | btnRefreshTables.setEnabled(cmb.getItemCount() > 0); 720 | } 721 | } 722 | } 723 | 724 | class FilterComboTextEdited implements ActionListener 725 | { 726 | @Override 727 | public void actionPerformed(ActionEvent e) 728 | { 729 | if (e.getActionCommand().equals("comboBoxEdited")) 730 | { 731 | String filterText = cmbFilter.getSelectedItem().toString(); 732 | 733 | if (filterText == null || filterText.trim().isEmpty()) 734 | return; 735 | 736 | DefaultComboBoxModel model = (DefaultComboBoxModel) cmbFilter.getModel(); 737 | 738 | if (model.getIndexOf(filterText) != -1) 739 | model.removeElement(filterText); 740 | 741 | cmbFilter.insertItemAt(filterText, 0); 742 | cmbFilter.setSelectedItem(filterText); 743 | } 744 | } 745 | } 746 | 747 | class ClassTableSelectionListener implements ListSelectionListener 748 | { 749 | private final JTable table; 750 | 751 | public ClassTableSelectionListener(JTable table) 752 | { 753 | this.table = table; 754 | } 755 | 756 | @Override 757 | public void valueChanged(ListSelectionEvent e) 758 | { 759 | if (!e.getValueIsAdjusting() && !table.getModel().equals(classesDefaultModel)) 760 | { 761 | int i = table.getSelectedRow(); 762 | if (i > -1) 763 | { 764 | savePrefs(); 765 | String pkg = (String) table.getModel().getValueAt(table.convertRowIndexToModel(i), 0); 766 | String name = (String) table.getModel().getValueAt(table.convertRowIndexToModel(i), 1); 767 | tblMethods.setModel(currentLoader.getMethodModel(pkg + "/" + name)); 768 | tblMethods.setEnabled(true); 769 | tblFields.setModel(currentLoader.getFieldModel(pkg + "/" + name)); 770 | tblFields.setEnabled(true); 771 | tblParams.setModel(paramsDefaultModel); 772 | tblParams.setEnabled(true); 773 | new TableColumnAdjuster(tblMethods).adjustColumns(); 774 | new TableColumnAdjuster(tblFields).adjustColumns(); 775 | loadPrefs(true); 776 | } 777 | else 778 | { 779 | tblMethods.setModel(methodsDefaultModel); 780 | tblMethods.setEnabled(false); 781 | tblFields.setModel(fieldsDefaultModel); 782 | tblFields.setEnabled(false); 783 | tblParams.setModel(paramsDefaultModel); 784 | tblParams.setEnabled(false); 785 | } 786 | } 787 | } 788 | } 789 | 790 | class MethodTableSelectionListener implements ListSelectionListener 791 | { 792 | private final JTable table; 793 | 794 | public MethodTableSelectionListener(JTable table) 795 | { 796 | this.table = table; 797 | } 798 | 799 | @Override 800 | public void valueChanged(ListSelectionEvent e) 801 | { 802 | if (!e.getValueIsAdjusting() && !table.getModel().equals(methodsDefaultModel)) 803 | { 804 | int i = table.getSelectedRow(); 805 | if (i > -1) 806 | { 807 | savePrefs(); 808 | String name = (String) table.getModel().getValueAt(table.convertRowIndexToModel(i), 1); 809 | tblParams.setModel(currentLoader.getParamModel(name)); 810 | tblParams.setEnabled(true); 811 | new TableColumnAdjuster(tblParams).adjustColumns(); 812 | loadPrefs(true); 813 | } 814 | else 815 | { 816 | tblParams.setModel(paramsDefaultModel); 817 | tblParams.setEnabled(false); 818 | } 819 | } 820 | } 821 | } 822 | 823 | class SearchActionListener implements ActionListener 824 | { 825 | @Override 826 | public void actionPerformed(ActionEvent e) 827 | { 828 | if (curTask != null && curTask.isAlive() || cmbFilter.getItemCount() == 0) 829 | return; 830 | 831 | String filterText = cmbFilter.getSelectedItem().toString(); 832 | 833 | if (filterText != null && !filterText.trim().isEmpty()) 834 | { 835 | DefaultComboBoxModel model = (DefaultComboBoxModel) cmbFilter.getModel(); 836 | 837 | if (model.getIndexOf(filterText) != -1) 838 | model.removeElement(filterText); 839 | 840 | cmbFilter.insertItemAt(filterText, 0); 841 | cmbFilter.setSelectedItem(filterText); 842 | } 843 | 844 | savePrefs(); 845 | 846 | cmbFilter.setEnabled(false); 847 | btnSearch.setEnabled(false); 848 | pnlProgress.setVisible(true); 849 | tblClasses.setModel(classesDefaultModel); 850 | tblClasses.setEnabled(false); 851 | tblMethods.setModel(methodsDefaultModel); 852 | tblMethods.setEnabled(false); 853 | tblParams.setModel(paramsDefaultModel); 854 | tblParams.setEnabled(false); 855 | tblFields.setModel(fieldsDefaultModel); 856 | tblFields.setEnabled(false); 857 | 858 | loadPrefs(true); 859 | 860 | curTask = new Thread() 861 | { 862 | @Override 863 | public void run() 864 | { 865 | boolean crashed = false; 866 | 867 | try 868 | { 869 | IProgressListener progress = new IProgressListener() 870 | { 871 | private String currentText; 872 | 873 | @Override 874 | public void start(final int max, final String text) 875 | { 876 | currentText = text.equals("") ? " " : text; 877 | SwingUtilities.invokeLater(new Runnable() 878 | { 879 | @Override 880 | public void run() 881 | { 882 | progressBar.setString(currentText); 883 | if (max >= 0) 884 | progressBar.setMaximum(max); 885 | progressBar.setValue(0); 886 | } 887 | }); 888 | } 889 | 890 | @Override 891 | public void set(final int value) 892 | { 893 | SwingUtilities.invokeLater(new Runnable() 894 | { 895 | @Override 896 | public void run() 897 | { 898 | progressBar.setValue(value); 899 | } 900 | }); 901 | } 902 | 903 | @Override 904 | public void set(final int value, final String text) 905 | { 906 | currentText = text.equals("") ? " " : text; 907 | SwingUtilities.invokeLater(new Runnable() 908 | { 909 | @Override 910 | public void run() 911 | { 912 | progressBar.setValue(value); 913 | progressBar.setString(currentText); 914 | } 915 | }); 916 | } 917 | 918 | @Override 919 | public void setMax(final int max) 920 | { 921 | SwingUtilities.invokeLater(new Runnable() 922 | { 923 | @Override 924 | public void run() 925 | { 926 | progressBar.setMaximum(max); 927 | } 928 | }); 929 | } 930 | }; 931 | 932 | progress.start(0, "Searching MCP objects for input"); 933 | tblClasses.setModel(currentLoader.getSearchResults(cmbFilter.getSelectedItem().toString(), progress)); 934 | tblClasses.setEnabled(true); 935 | new TableColumnAdjuster(tblClasses).adjustColumns(); 936 | loadPrefs(true); 937 | 938 | if (tblClasses.getRowCount() > 0) 939 | { 940 | String pkg = (String) tblClasses.getModel().getValueAt(0, 0); 941 | String name = (String) tblClasses.getModel().getValueAt(0, 1); 942 | tblMethods.setModel(currentLoader.getMethodModel(pkg + "/" + name)); 943 | tblMethods.setEnabled(true); 944 | tblFields.setModel(currentLoader.getFieldModel(pkg + "/" + name)); 945 | tblFields.setEnabled(true); 946 | tblParams.setModel(paramsDefaultModel); 947 | tblParams.setEnabled(true); 948 | new TableColumnAdjuster(tblMethods).adjustColumns(); 949 | new TableColumnAdjuster(tblFields).adjustColumns(); 950 | loadPrefs(true); 951 | 952 | if (cmbFilter.getSelectedItem().toString().trim().startsWith("field") && tblFields.getRowCount() > 0) 953 | { 954 | for (int i = 0; i < tblFields.getRowCount(); i++) 955 | { 956 | if (((String) tblFields.getModel().getValueAt(i, 1)).contains(cmbFilter.getSelectedItem().toString())) 957 | { 958 | final int rowIndex = i; 959 | tblFields.setRowSelectionInterval(rowIndex, rowIndex); 960 | tblFields.setColumnSelectionInterval(1, 1); 961 | tblFields.requestFocus(); 962 | 963 | SwingUtilities.invokeLater(new Runnable() 964 | { 965 | @Override 966 | public void run() 967 | { 968 | tblFields.scrollRectToVisible(tblFields.getCellRect(rowIndex, 0, true)); 969 | } 970 | }); 971 | 972 | break; 973 | } 974 | } 975 | } 976 | else if (cmbFilter.getSelectedItem().toString().trim().startsWith("func") && tblMethods.getRowCount() > 0) 977 | { 978 | for (int i = 0; i < tblMethods.getRowCount(); i++) 979 | { 980 | if (((String) tblMethods.getModel().getValueAt(i, 1)).contains(cmbFilter.getSelectedItem().toString())) 981 | { 982 | final int rowIndex = i; 983 | tblMethods.setRowSelectionInterval(rowIndex, rowIndex); 984 | tblMethods.setColumnSelectionInterval(1, 1); 985 | tblMethods.requestFocus(); 986 | 987 | SwingUtilities.invokeLater(new Runnable() 988 | { 989 | @Override 990 | public void run() 991 | { 992 | tblMethods.scrollRectToVisible(tblMethods.getCellRect(rowIndex, 0, true)); 993 | } 994 | }); 995 | 996 | break; 997 | } 998 | } 999 | 1000 | } 1001 | } 1002 | 1003 | loadPrefs(true); 1004 | } 1005 | catch (Exception e) 1006 | { 1007 | String s = getStackTraceMessage( 1008 | "An error has occurred - give bspkrs this stack trace (which has been copied to the clipboard)\n", e); 1009 | 1010 | System.err.println(s); 1011 | 1012 | crashed = true; 1013 | 1014 | final String errMsg = s; 1015 | SwingUtilities.invokeLater(new Runnable() 1016 | { 1017 | @Override 1018 | public void run() 1019 | { 1020 | progressBar.setString(" "); 1021 | progressBar.setValue(0); 1022 | 1023 | Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(errMsg), null); 1024 | JOptionPane.showMessageDialog(MappingGui.this, errMsg, "MMV - Error", JOptionPane.ERROR_MESSAGE); 1025 | } 1026 | }); 1027 | } 1028 | finally 1029 | { 1030 | if (!crashed) 1031 | { 1032 | SwingUtilities.invokeLater(new Runnable() 1033 | { 1034 | @Override 1035 | public void run() 1036 | { 1037 | progressBar.setString(" "); 1038 | progressBar.setValue(0); 1039 | cmbFilter.setEnabled(true); 1040 | } 1041 | }); 1042 | } 1043 | pnlProgress.setVisible(false); 1044 | cmbFilter.setEnabled(true); 1045 | btnSearch.setEnabled(true); 1046 | } 1047 | } 1048 | }; 1049 | 1050 | curTask.start(); 1051 | } 1052 | } 1053 | 1054 | class RefreshActionListener implements ActionListener 1055 | { 1056 | @Override 1057 | public void actionPerformed(ActionEvent e) 1058 | { 1059 | if (curTask != null && curTask.isAlive()) 1060 | return; 1061 | 1062 | final String mappingVersion = (String) cmbMappingVersion.getSelectedItem(); 1063 | savePrefs(); 1064 | 1065 | pnlFilter.setVisible(false); 1066 | pnlProgress.setVisible(true); 1067 | tblClasses.setModel(classesDefaultModel); 1068 | tblClasses.setEnabled(false); 1069 | tblMethods.setModel(methodsDefaultModel); 1070 | tblMethods.setEnabled(false); 1071 | tblParams.setModel(paramsDefaultModel); 1072 | tblParams.setEnabled(false); 1073 | tblFields.setModel(fieldsDefaultModel); 1074 | tblFields.setEnabled(false); 1075 | 1076 | loadPrefs(true); 1077 | 1078 | curTask = new Thread() 1079 | { 1080 | @Override 1081 | public void run() 1082 | { 1083 | boolean crashed = false; 1084 | 1085 | try 1086 | { 1087 | IProgressListener progress = new IProgressListener() 1088 | { 1089 | private String currentText; 1090 | 1091 | @Override 1092 | public void start(final int max, final String text) 1093 | { 1094 | currentText = text.equals("") ? " " : text; 1095 | SwingUtilities.invokeLater(new Runnable() 1096 | { 1097 | @Override 1098 | public void run() 1099 | { 1100 | progressBar.setString(currentText); 1101 | if (max >= 0) 1102 | progressBar.setMaximum(max); 1103 | progressBar.setValue(0); 1104 | } 1105 | }); 1106 | } 1107 | 1108 | @Override 1109 | public void set(final int value) 1110 | { 1111 | SwingUtilities.invokeLater(new Runnable() 1112 | { 1113 | @Override 1114 | public void run() 1115 | { 1116 | progressBar.setValue(value); 1117 | } 1118 | }); 1119 | } 1120 | 1121 | @Override 1122 | public void set(final int value, final String text) 1123 | { 1124 | currentText = text.equals("") ? " " : text; 1125 | SwingUtilities.invokeLater(new Runnable() 1126 | { 1127 | @Override 1128 | public void run() 1129 | { 1130 | progressBar.setValue(value); 1131 | progressBar.setString(currentText); 1132 | } 1133 | }); 1134 | } 1135 | 1136 | @Override 1137 | public void setMax(final int max) 1138 | { 1139 | SwingUtilities.invokeLater(new Runnable() 1140 | { 1141 | @Override 1142 | public void run() 1143 | { 1144 | progressBar.setMaximum(max); 1145 | } 1146 | }); 1147 | } 1148 | }; 1149 | 1150 | if (!mcpInstances.containsKey(mappingVersion) || chkForceRefresh.isSelected()) 1151 | { 1152 | progress.start(0, "Reading MCP configuration"); 1153 | currentLoader = new McpMappingLoader(MappingGui.this, mappingVersion, progress); 1154 | mcpInstances.put(mappingVersion, currentLoader); 1155 | chkForceRefresh.setSelected(false); 1156 | } 1157 | else 1158 | currentLoader = mcpInstances.get(mappingVersion); 1159 | 1160 | tblClasses.setModel(currentLoader.getClassModel()); 1161 | tblClasses.setEnabled(true); 1162 | new TableColumnAdjuster(tblClasses).adjustColumns(); 1163 | loadPrefs(true); 1164 | } 1165 | catch (CantLoadMCPMappingException e) 1166 | { 1167 | String s = getStackTraceMessage("", e); 1168 | 1169 | System.err.println(s); 1170 | 1171 | crashed = true; 1172 | 1173 | final String errMsg = s; 1174 | SwingUtilities.invokeLater(new Runnable() 1175 | { 1176 | @Override 1177 | public void run() 1178 | { 1179 | progressBar.setString(" "); 1180 | progressBar.setValue(0); 1181 | 1182 | JOptionPane.showMessageDialog(MappingGui.this, errMsg, "MMV - Error", JOptionPane.ERROR_MESSAGE); 1183 | } 1184 | }); 1185 | } 1186 | catch (Exception e) 1187 | { 1188 | String s = getStackTraceMessage( 1189 | "An error has occurred - give bspkrs this stack trace (which has been copied to the clipboard)\n", e); 1190 | 1191 | System.err.println(s); 1192 | 1193 | crashed = true; 1194 | 1195 | final String errMsg = s; 1196 | SwingUtilities.invokeLater(new Runnable() 1197 | { 1198 | @Override 1199 | public void run() 1200 | { 1201 | progressBar.setString(" "); 1202 | progressBar.setValue(0); 1203 | 1204 | Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(errMsg), null); 1205 | JOptionPane.showMessageDialog(MappingGui.this, errMsg, "MMV - Error", JOptionPane.ERROR_MESSAGE); 1206 | } 1207 | }); 1208 | } 1209 | finally 1210 | { 1211 | if (!crashed) 1212 | { 1213 | SwingUtilities.invokeLater(new Runnable() 1214 | { 1215 | @Override 1216 | public void run() 1217 | { 1218 | progressBar.setString(" "); 1219 | progressBar.setValue(0); 1220 | cmbFilter.setEnabled(true); 1221 | } 1222 | }); 1223 | } 1224 | pnlProgress.setVisible(false); 1225 | pnlFilter.setVisible(true); 1226 | cmbFilter.setEnabled(true); 1227 | btnSearch.setEnabled(true); 1228 | // btnSave.setEnabled(currentLoader.hasPendingEdits()); 1229 | btnGetBotCommands.setEnabled(currentLoader.hasPendingCommands()); 1230 | } 1231 | } 1232 | }; 1233 | 1234 | curTask.start(); 1235 | } 1236 | } 1237 | 1238 | public static void showHTMLDialog(Component parentComponent, Object message, String title, int messageType) 1239 | { 1240 | JLabel label = new JLabel(); 1241 | Font font = label.getFont(); 1242 | 1243 | StringBuffer style = new StringBuffer("font-family:" + font.getFamily() + ";"); 1244 | style.append("font-weight:" + (font.isBold() ? "bold" : "normal") + ";"); 1245 | style.append("font-size:" + font.getSize() + "pt;"); 1246 | 1247 | JEditorPane ep = new JEditorPane("text/html", "" + message.toString() + ""); 1248 | 1249 | ep.addHyperlinkListener(new HyperlinkListener() 1250 | { 1251 | @Override 1252 | public void hyperlinkUpdate(HyperlinkEvent e) 1253 | { 1254 | if (e.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)) 1255 | { 1256 | try 1257 | { 1258 | Desktop.getDesktop().browse(e.getURL().toURI()); 1259 | } 1260 | catch (Throwable ignore) 1261 | {} 1262 | } 1263 | } 1264 | }); 1265 | // Dunno why, but if I do this the About dialog no longer gets cut off... 1266 | ep.setSize(100, 100); 1267 | ep.setEditable(false); 1268 | ep.setBackground(label.getBackground()); 1269 | JOptionPane.showMessageDialog(parentComponent, ep, title, messageType); 1270 | } 1271 | } 1272 | -------------------------------------------------------------------------------- /src/main/java/bspkrs/mmv/gui/TableColumnAdjuster.java: -------------------------------------------------------------------------------- 1 | /* 2 | * As found at http://tips4java.wordpress.com/2008/11/10/table-column-adjuster/ 3 | * on 11/12/2013 4 | */ 5 | package bspkrs.mmv.gui; 6 | 7 | import java.awt.Component; 8 | import java.awt.event.ActionEvent; 9 | import java.beans.PropertyChangeEvent; 10 | import java.beans.PropertyChangeListener; 11 | import java.util.HashMap; 12 | import java.util.Map; 13 | 14 | import javax.swing.AbstractAction; 15 | import javax.swing.Action; 16 | import javax.swing.JTable; 17 | import javax.swing.KeyStroke; 18 | import javax.swing.event.TableModelEvent; 19 | import javax.swing.event.TableModelListener; 20 | import javax.swing.table.TableCellRenderer; 21 | import javax.swing.table.TableColumn; 22 | import javax.swing.table.TableColumnModel; 23 | import javax.swing.table.TableModel; 24 | 25 | /* 26 | * Class to manage the widths of colunmns in a table. 27 | * 28 | * Various properties control how the width of the column is calculated. 29 | * Another property controls whether column width calculation should be dynamic. 30 | * Finally, various Actions will be added to the table to allow the user 31 | * to customize the functionality. 32 | * 33 | * This class was designed to be used with tables that use an auto resize mode 34 | * of AUTO_RESIZE_OFF. With all other modes you are constrained as the width 35 | * of the columns must fit inside the table. So if you increase one column, one 36 | * or more of the other columns must decrease. Because of this the resize mode 37 | * of RESIZE_ALL_COLUMNS will work the best. 38 | */ 39 | 40 | public class TableColumnAdjuster implements PropertyChangeListener, TableModelListener 41 | { 42 | private JTable table; 43 | private int spacing; 44 | private boolean isColumnHeaderIncluded; 45 | private boolean isColumnDataIncluded; 46 | private boolean isOnlyAdjustLarger; 47 | private boolean isDynamicAdjustment; 48 | private Map columnSizes = new HashMap(); 49 | 50 | /* 51 | * Specify the table and use default spacing 52 | */ 53 | public TableColumnAdjuster(JTable table) 54 | { 55 | this(table, 6); 56 | } 57 | 58 | /* 59 | * Specify the table and spacing 60 | */ 61 | public TableColumnAdjuster(JTable table, int spacing) 62 | { 63 | this.table = table; 64 | this.spacing = spacing; 65 | setColumnHeaderIncluded(true); 66 | setColumnDataIncluded(true); 67 | setOnlyAdjustLarger(true); 68 | setDynamicAdjustment(false); 69 | installActions(); 70 | } 71 | 72 | /* 73 | * Adjust the widths of all the columns in the table 74 | */ 75 | public void adjustColumns() 76 | { 77 | TableColumnModel tcm = table.getColumnModel(); 78 | 79 | for (int i = 0; i < tcm.getColumnCount(); i++) 80 | { 81 | adjustColumn(i); 82 | } 83 | } 84 | 85 | /* 86 | * Adjust the width of the specified column in the table 87 | */ 88 | public void adjustColumn(final int column) 89 | { 90 | TableColumn tableColumn = table.getColumnModel().getColumn(column); 91 | 92 | if (!tableColumn.getResizable()) 93 | return; 94 | 95 | int columnHeaderWidth = getColumnHeaderWidth(column); 96 | int columnDataWidth = getColumnDataWidth(column); 97 | int preferredWidth = Math.max(columnHeaderWidth, columnDataWidth); 98 | 99 | updateTableColumn(column, preferredWidth); 100 | } 101 | 102 | /* 103 | * Calculated the width based on the column name 104 | */ 105 | private int getColumnHeaderWidth(int column) 106 | { 107 | if (!isColumnHeaderIncluded) 108 | return 0; 109 | 110 | TableColumn tableColumn = table.getColumnModel().getColumn(column); 111 | Object value = tableColumn.getHeaderValue(); 112 | TableCellRenderer renderer = tableColumn.getHeaderRenderer(); 113 | 114 | if (renderer == null) 115 | { 116 | renderer = table.getTableHeader().getDefaultRenderer(); 117 | } 118 | 119 | Component c = renderer.getTableCellRendererComponent(table, value, false, false, -1, column); 120 | return c.getPreferredSize().width; 121 | } 122 | 123 | /* 124 | * Calculate the width based on the widest cell renderer for the 125 | * given column. 126 | */ 127 | private int getColumnDataWidth(int column) 128 | { 129 | if (!isColumnDataIncluded) 130 | return 0; 131 | 132 | int preferredWidth = 0; 133 | int maxWidth = table.getColumnModel().getColumn(column).getMaxWidth(); 134 | 135 | for (int row = 0; row < table.getRowCount(); row++) 136 | { 137 | preferredWidth = Math.max(preferredWidth, getCellDataWidth(row, column)); 138 | 139 | // We've exceeded the maximum width, no need to check other rows 140 | 141 | if (preferredWidth >= maxWidth) 142 | break; 143 | } 144 | 145 | return preferredWidth; 146 | } 147 | 148 | /* 149 | * Get the preferred width for the specified cell 150 | */ 151 | private int getCellDataWidth(int row, int column) 152 | { 153 | // Inovke the renderer for the cell to calculate the preferred width 154 | 155 | TableCellRenderer cellRenderer = table.getCellRenderer(row, column); 156 | Component c = table.prepareRenderer(cellRenderer, row, column); 157 | int width = c.getPreferredSize().width + table.getIntercellSpacing().width; 158 | 159 | return width; 160 | } 161 | 162 | /* 163 | * Update the TableColumn with the newly calculated width 164 | */ 165 | private void updateTableColumn(int column, int width) 166 | { 167 | final TableColumn tableColumn = table.getColumnModel().getColumn(column); 168 | 169 | if (!tableColumn.getResizable()) 170 | return; 171 | 172 | width += spacing; 173 | 174 | // Don't shrink the column width 175 | 176 | if (isOnlyAdjustLarger) 177 | { 178 | width = Math.max(width, tableColumn.getPreferredWidth()); 179 | } 180 | 181 | columnSizes.put(tableColumn, new Integer(tableColumn.getWidth())); 182 | table.getTableHeader().setResizingColumn(tableColumn); 183 | tableColumn.setWidth(width); 184 | } 185 | 186 | /* 187 | * Restore the widths of the columns in the table to its previous width 188 | */ 189 | public void restoreColumns() 190 | { 191 | TableColumnModel tcm = table.getColumnModel(); 192 | 193 | for (int i = 0; i < tcm.getColumnCount(); i++) 194 | { 195 | restoreColumn(i); 196 | } 197 | } 198 | 199 | /* 200 | * Restore the width of the specified column to its previous width 201 | */ 202 | private void restoreColumn(int column) 203 | { 204 | TableColumn tableColumn = table.getColumnModel().getColumn(column); 205 | Integer width = columnSizes.get(tableColumn); 206 | 207 | if (width != null) 208 | { 209 | table.getTableHeader().setResizingColumn(tableColumn); 210 | tableColumn.setWidth(width.intValue()); 211 | } 212 | } 213 | 214 | /* 215 | * Indicates whether to include the header in the width calculation 216 | */ 217 | public void setColumnHeaderIncluded(boolean isColumnHeaderIncluded) 218 | { 219 | this.isColumnHeaderIncluded = isColumnHeaderIncluded; 220 | } 221 | 222 | /* 223 | * Indicates whether to include the model data in the width calculation 224 | */ 225 | public void setColumnDataIncluded(boolean isColumnDataIncluded) 226 | { 227 | this.isColumnDataIncluded = isColumnDataIncluded; 228 | } 229 | 230 | /* 231 | * Indicates whether columns can only be increased in size 232 | */ 233 | public void setOnlyAdjustLarger(boolean isOnlyAdjustLarger) 234 | { 235 | this.isOnlyAdjustLarger = isOnlyAdjustLarger; 236 | } 237 | 238 | /* 239 | * Indicate whether changes to the model should cause the width to be 240 | * dynamically recalculated. 241 | */ 242 | public void setDynamicAdjustment(boolean isDynamicAdjustment) 243 | { 244 | // May need to add or remove the TableModelListener when changed 245 | 246 | if (this.isDynamicAdjustment != isDynamicAdjustment) 247 | { 248 | if (isDynamicAdjustment) 249 | { 250 | table.addPropertyChangeListener(this); 251 | table.getModel().addTableModelListener(this); 252 | } 253 | else 254 | { 255 | table.removePropertyChangeListener(this); 256 | table.getModel().removeTableModelListener(this); 257 | } 258 | } 259 | 260 | this.isDynamicAdjustment = isDynamicAdjustment; 261 | } 262 | 263 | // 264 | // Implement the PropertyChangeListener 265 | // 266 | @Override 267 | public void propertyChange(PropertyChangeEvent e) 268 | { 269 | // When the TableModel changes we need to update the listeners 270 | // and column widths 271 | 272 | if ("model".equals(e.getPropertyName())) 273 | { 274 | TableModel model = (TableModel) e.getOldValue(); 275 | model.removeTableModelListener(this); 276 | 277 | model = (TableModel) e.getNewValue(); 278 | model.addTableModelListener(this); 279 | adjustColumns(); 280 | } 281 | } 282 | 283 | // 284 | // Implement the TableModelListener 285 | // 286 | @Override 287 | public void tableChanged(TableModelEvent e) 288 | { 289 | if (!isColumnDataIncluded) 290 | return; 291 | 292 | // A cell has been updated 293 | 294 | if (e.getType() == TableModelEvent.UPDATE) 295 | { 296 | int column = table.convertColumnIndexToView(e.getColumn()); 297 | 298 | // Only need to worry about an increase in width for this cell 299 | 300 | if (isOnlyAdjustLarger) 301 | { 302 | int row = e.getFirstRow(); 303 | TableColumn tableColumn = table.getColumnModel().getColumn(column); 304 | 305 | if (tableColumn.getResizable()) 306 | { 307 | int width = getCellDataWidth(row, column); 308 | updateTableColumn(column, width); 309 | } 310 | } 311 | 312 | // Could be an increase of decrease so check all rows 313 | 314 | else 315 | { 316 | adjustColumn(column); 317 | } 318 | } 319 | 320 | // The update affected more than one column so adjust all columns 321 | 322 | else 323 | { 324 | adjustColumns(); 325 | } 326 | } 327 | 328 | /* 329 | * Install Actions to give user control of certain functionality. 330 | */ 331 | private void installActions() 332 | { 333 | installColumnAction(true, true, "adjustColumn", "control ADD"); 334 | installColumnAction(false, true, "adjustColumns", "control shift ADD"); 335 | installColumnAction(true, false, "restoreColumn", "control SUBTRACT"); 336 | installColumnAction(false, false, "restoreColumns", "control shift SUBTRACT"); 337 | 338 | installToggleAction(true, false, "toggleDynamic", "control MULTIPLY"); 339 | installToggleAction(false, true, "toggleLarger", "control DIVIDE"); 340 | } 341 | 342 | /* 343 | * Update the input and action maps with a new ColumnAction 344 | */ 345 | private void installColumnAction( 346 | boolean isSelectedColumn, boolean isAdjust, String key, String keyStroke) 347 | { 348 | Action action = new ColumnAction(isSelectedColumn, isAdjust); 349 | KeyStroke ks = KeyStroke.getKeyStroke(keyStroke); 350 | table.getInputMap().put(ks, key); 351 | table.getActionMap().put(key, action); 352 | } 353 | 354 | /* 355 | * Update the input and action maps with new ToggleAction 356 | */ 357 | private void installToggleAction( 358 | boolean isToggleDynamic, boolean isToggleLarger, String key, String keyStroke) 359 | { 360 | Action action = new ToggleAction(isToggleDynamic, isToggleLarger); 361 | KeyStroke ks = KeyStroke.getKeyStroke(keyStroke); 362 | table.getInputMap().put(ks, key); 363 | table.getActionMap().put(key, action); 364 | } 365 | 366 | /* 367 | * Action to adjust or restore the width of a single column or all columns 368 | */ 369 | class ColumnAction extends AbstractAction 370 | { 371 | private static final long serialVersionUID = 1L; 372 | private boolean isSelectedColumn; 373 | private boolean isAdjust; 374 | 375 | public ColumnAction(boolean isSelectedColumn, boolean isAdjust) 376 | { 377 | this.isSelectedColumn = isSelectedColumn; 378 | this.isAdjust = isAdjust; 379 | } 380 | 381 | @Override 382 | public void actionPerformed(ActionEvent e) 383 | { 384 | // Handle selected column(s) width change actions 385 | 386 | if (isSelectedColumn) 387 | { 388 | int[] columns = table.getSelectedColumns(); 389 | 390 | for (int i = 0; i < columns.length; i++) 391 | { 392 | if (isAdjust) 393 | adjustColumn(columns[i]); 394 | else 395 | restoreColumn(columns[i]); 396 | } 397 | } 398 | else 399 | { 400 | if (isAdjust) 401 | adjustColumns(); 402 | else 403 | restoreColumns(); 404 | } 405 | } 406 | } 407 | 408 | /* 409 | * Toggle properties of the TableColumnAdjuster so the user can 410 | * customize the functionality to their preferences 411 | */ 412 | class ToggleAction extends AbstractAction 413 | { 414 | private static final long serialVersionUID = 1L; 415 | private boolean isToggleDynamic; 416 | private boolean isToggleLarger; 417 | 418 | public ToggleAction(boolean isToggleDynamic, boolean isToggleLarger) 419 | { 420 | this.isToggleDynamic = isToggleDynamic; 421 | this.isToggleLarger = isToggleLarger; 422 | } 423 | 424 | @Override 425 | public void actionPerformed(ActionEvent e) 426 | { 427 | if (isToggleDynamic) 428 | { 429 | setDynamicAdjustment(!isDynamicAdjustment); 430 | return; 431 | } 432 | 433 | if (isToggleLarger) 434 | { 435 | setOnlyAdjustLarger(!isOnlyAdjustLarger); 436 | return; 437 | } 438 | } 439 | } 440 | } 441 | -------------------------------------------------------------------------------- /src/main/java/bspkrs/mmv/version/AppVersionChecker.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 bspkrs 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 5 | * files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 7 | * Software is furnished to do so, subject to the following conditions: 8 | * 9 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 12 | * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 13 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 14 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | */ 16 | package bspkrs.mmv.version; 17 | 18 | import java.net.URL; 19 | import java.net.URLConnection; 20 | import java.util.ArrayList; 21 | import java.util.List; 22 | import java.util.Scanner; 23 | import java.util.prefs.Preferences; 24 | 25 | public class AppVersionChecker 26 | { 27 | private URL versionURL; 28 | private final String appName; 29 | private String newVersion; 30 | private final String currentVersion; 31 | private String updateURL; 32 | private String[] logMsg; 33 | private String[] dialogMsg; 34 | private final Preferences versionCheckTracker; 35 | private final String LAST_VERSION_FOUND = "lastversionfound"; 36 | private final String RUNS_SINCE_LAST_MSG = "runs_since_last_message"; 37 | private final String CHECK_ERROR = "check_error"; 38 | private String lastNewVersionFound; 39 | private final boolean errorDetected; 40 | private int runsSinceLastMessage; 41 | 42 | public AppVersionChecker(String appName, String currentVersion, String versionURL, String updateURL, String[] logMsg, String[] dialogMsg, int timeoutMS) 43 | { 44 | this.appName = appName; 45 | this.currentVersion = currentVersion; 46 | this.updateURL = updateURL; 47 | this.logMsg = logMsg; 48 | this.dialogMsg = dialogMsg; 49 | 50 | try 51 | { 52 | if (versionURL.startsWith("http://dl.dropboxusercontent.com")) 53 | versionURL = versionURL.replaceFirst("http", "https"); 54 | 55 | this.versionURL = new URL(versionURL); 56 | } 57 | catch (Throwable ignore) 58 | {} 59 | 60 | String[] versionLines = loadTextFromURL(this.versionURL, new String[] { CHECK_ERROR }, timeoutMS); 61 | 62 | if ((versionLines.length == 0) || versionLines[0].trim().equals("")) 63 | newVersion = CHECK_ERROR; 64 | else 65 | newVersion = versionLines[0].trim(); 66 | 67 | errorDetected = newVersion.equals(CHECK_ERROR); 68 | 69 | versionCheckTracker = Preferences.userNodeForPackage(AppVersionChecker.class); 70 | 71 | lastNewVersionFound = versionCheckTracker.get(LAST_VERSION_FOUND, currentVersion); 72 | 73 | if (lastNewVersionFound.equals("")) 74 | lastNewVersionFound = currentVersion; 75 | 76 | runsSinceLastMessage = versionCheckTracker.getInt(RUNS_SINCE_LAST_MSG, 0); 77 | 78 | if (errorDetected) 79 | newVersion = lastNewVersionFound; 80 | 81 | if (!errorDetected && !isCurrentVersion(lastNewVersionFound, newVersion)) 82 | { 83 | runsSinceLastMessage = 0; 84 | lastNewVersionFound = newVersion; 85 | } 86 | else 87 | runsSinceLastMessage = runsSinceLastMessage % 10; 88 | 89 | versionCheckTracker.putInt(RUNS_SINCE_LAST_MSG, runsSinceLastMessage + 1); 90 | versionCheckTracker.put(LAST_VERSION_FOUND, lastNewVersionFound); 91 | 92 | // Override instantiated updateURL with second line of version file if it exists and is non-blank 93 | if ((versionLines.length > 1) && (versionLines[1].trim().length() != 0)) 94 | this.updateURL = versionLines[1]; 95 | 96 | setLogMessage(logMsg); 97 | setDialogMessage(dialogMsg); 98 | } 99 | 100 | public AppVersionChecker(String appName, String oldVer, String versionURL, String updateURL) 101 | { 102 | this(appName, oldVer, versionURL, updateURL, new String[] { "{appName} {oldVer} is out of date! Visit {updateURL} to download the latest release ({newVer})." }, new String[] { "{appName} {newVer} is out! Download the latest from {updateURL}" }, 5000); 103 | } 104 | 105 | public void checkVersionWithLogging() 106 | { 107 | if (!isCurrentVersion(currentVersion, newVersion)) 108 | for (String msg : logMsg) 109 | System.out.println(msg); 110 | } 111 | 112 | public void setLogMessage(String[] logMsg) 113 | { 114 | this.logMsg = logMsg; 115 | 116 | for (int i = 0; i < this.logMsg.length; i++) 117 | this.logMsg[i] = replaceAllTags(this.logMsg[i]); 118 | } 119 | 120 | public void setDialogMessage(String[] dialogMsg) 121 | { 122 | this.dialogMsg = dialogMsg; 123 | 124 | for (int i = 0; i < this.dialogMsg.length; i++) 125 | this.dialogMsg[i] = replaceAllTags(this.dialogMsg[i]); 126 | 127 | } 128 | 129 | public String[] getLogMessage() 130 | { 131 | return logMsg; 132 | } 133 | 134 | public String[] getDialogMessage() 135 | { 136 | return dialogMsg; 137 | } 138 | 139 | public boolean isCurrentVersion() 140 | { 141 | return isCurrentVersion(runsSinceLastMessage == 0 ? currentVersion : lastNewVersionFound, newVersion); 142 | } 143 | 144 | public static boolean isCurrentVersion(String currentVersion, String newVersion) 145 | { 146 | return new NaturalOrderComparator().compare(currentVersion, newVersion) >= 0; 147 | } 148 | 149 | private String replaceAllTags(String s) 150 | { 151 | return s.replace("{oldVer}", currentVersion).replace("{newVer}", newVersion).replace("{appName}", appName).replace("{updateURL}", updateURL); 152 | } 153 | 154 | public static String[] loadTextFromURL(URL url, String[] defaultValue, int timeoutMS) 155 | { 156 | List arraylist = new ArrayList(); 157 | Scanner scanner = null; 158 | try 159 | { 160 | URLConnection uc = url.openConnection(); 161 | uc.setReadTimeout(timeoutMS); 162 | uc.setConnectTimeout(timeoutMS); 163 | scanner = new Scanner(uc.getInputStream(), "UTF-8"); 164 | } 165 | catch (Throwable e) 166 | { 167 | return defaultValue; 168 | } 169 | 170 | while (scanner.hasNextLine()) 171 | { 172 | arraylist.add(scanner.nextLine()); 173 | } 174 | scanner.close(); 175 | return arraylist.toArray(new String[arraylist.size()]); 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /src/main/java/bspkrs/mmv/version/NaturalOrderComparator.java: -------------------------------------------------------------------------------- 1 | /* 2 | NaturalOrderComparator.java -- Perform 'natural order' comparisons of strings in Java. 3 | Copyright (C) 2003 by Pierre-Luc Paour 4 | 5 | Based on the C version by Martin Pool, of which this is more or less a straight conversion. 6 | Copyright (C) 2000 by Martin Pool 7 | 8 | This software is provided 'as-is', without any express or implied 9 | warranty. In no event will the authors be held liable for any damages 10 | arising from the use of this software. 11 | 12 | Permission is granted to anyone to use this software for any purpose, 13 | including commercial applications, and to alter it and redistribute it 14 | freely, subject to the following restrictions: 15 | 16 | 1. The origin of this software must not be misrepresented; you must not 17 | claim that you wrote the original software. If you use this software 18 | in a product, an acknowledgment in the product documentation would be 19 | appreciated but is not required. 20 | 2. Altered source versions must be plainly marked as such, and must not be 21 | misrepresented as being the original software. 22 | 3. This notice may not be removed or altered from any source distribution. 23 | 24 | changes by bspkrs: cleaned up Java compiler warnings 25 | */ 26 | package bspkrs.mmv.version; 27 | 28 | import java.util.Comparator; 29 | 30 | public class NaturalOrderComparator implements Comparator 31 | { 32 | int compareRight(String a, String b) 33 | { 34 | int bias = 0; 35 | int ia = 0; 36 | int ib = 0; 37 | 38 | // The longest run of digits wins. That aside, the greatest 39 | // value wins, but we can't know that it will until we've scanned 40 | // both numbers to know that they have the same magnitude, so we 41 | // remember it in BIAS. 42 | for (;; ia++, ib++) 43 | { 44 | char ca = charAt(a, ia); 45 | char cb = charAt(b, ib); 46 | 47 | if (!Character.isDigit(ca) && !Character.isDigit(cb)) 48 | { 49 | return bias; 50 | } 51 | else if (!Character.isDigit(ca)) 52 | { 53 | return -1; 54 | } 55 | else if (!Character.isDigit(cb)) 56 | { 57 | return +1; 58 | } 59 | else if (ca < cb) 60 | { 61 | if (bias == 0) 62 | { 63 | bias = -1; 64 | } 65 | } 66 | else if (ca > cb) 67 | { 68 | if (bias == 0) 69 | bias = +1; 70 | } 71 | else if (ca == 0 && cb == 0) 72 | { 73 | return bias; 74 | } 75 | } 76 | } 77 | 78 | @Override 79 | public int compare(Object o1, Object o2) 80 | { 81 | String a = o1.toString(); 82 | String b = o2.toString(); 83 | 84 | int ia = 0, ib = 0; 85 | int nza = 0, nzb = 0; 86 | char ca, cb; 87 | int result; 88 | 89 | while (true) 90 | { 91 | // only count the number of zeroes leading the last number compared 92 | nza = nzb = 0; 93 | 94 | ca = charAt(a, ia); 95 | cb = charAt(b, ib); 96 | 97 | // skip over leading spaces or zeros 98 | while (Character.isSpaceChar(ca) || ca == '0') 99 | { 100 | if (ca == '0') 101 | { 102 | nza++; 103 | } 104 | else 105 | { 106 | // only count consecutive zeroes 107 | nza = 0; 108 | } 109 | 110 | ca = charAt(a, ++ia); 111 | } 112 | 113 | while (Character.isSpaceChar(cb) || cb == '0') 114 | { 115 | if (cb == '0') 116 | { 117 | nzb++; 118 | } 119 | else 120 | { 121 | // only count consecutive zeroes 122 | nzb = 0; 123 | } 124 | 125 | cb = charAt(b, ++ib); 126 | } 127 | 128 | // process run of digits 129 | if (Character.isDigit(ca) && Character.isDigit(cb)) 130 | { 131 | if ((result = compareRight(a.substring(ia), b.substring(ib))) != 0) 132 | { 133 | return result; 134 | } 135 | } 136 | 137 | if (ca == 0 && cb == 0) 138 | { 139 | // The strings compare the same. Perhaps the caller 140 | // will want to call strcmp to break the tie. 141 | return nza - nzb; 142 | } 143 | 144 | if (ca < cb) 145 | { 146 | return -1; 147 | } 148 | else if (ca > cb) 149 | { 150 | return +1; 151 | } 152 | 153 | ++ia; 154 | ++ib; 155 | } 156 | } 157 | 158 | static char charAt(String s, int i) 159 | { 160 | if (i >= s.length()) 161 | { 162 | return 0; 163 | } 164 | else 165 | { 166 | return s.charAt(i); 167 | } 168 | } 169 | } -------------------------------------------------------------------------------- /src/main/java/immibis/bon/IProgressListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Alex "immibis" Campbell 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 5 | * files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 7 | * Software is furnished to do so, subject to the following conditions: 8 | * 9 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 12 | * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 13 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 14 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | */ 16 | package immibis.bon; 17 | 18 | public interface IProgressListener 19 | { 20 | public void start(int max, String text); 21 | 22 | public void set(int value); 23 | 24 | public void set(int value, String text); 25 | 26 | public void setMax(int max); 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/immibis/bon/NameSet.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Alex "immibis" Campbell 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 5 | * files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 7 | * Software is furnished to do so, subject to the following conditions: 8 | * 9 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 12 | * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 13 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 14 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | */ 16 | package immibis.bon; 17 | 18 | /** 19 | * E.g. "1.5.1 obfuscated", "1.5.1 searge", "1.5.1 MCP" are NameSets. 20 | */ 21 | public class NameSet 22 | { 23 | public static enum Type 24 | { 25 | OBF, 26 | SRG, 27 | MCP 28 | } 29 | 30 | public static enum Side 31 | { 32 | UNIVERSAL, 33 | CLIENT, 34 | SERVER 35 | } 36 | 37 | public final Type type; 38 | public final String mcVersion; 39 | public final Side side; 40 | 41 | public NameSet(Type type, Side side, String mcVersion) 42 | { 43 | this.type = type; 44 | this.side = side; 45 | this.mcVersion = mcVersion; 46 | } 47 | 48 | @Override 49 | public boolean equals(Object obj) 50 | { 51 | try 52 | { 53 | NameSet ns = (NameSet) obj; 54 | return ns.type == type && ns.side == side && ns.mcVersion.equals(mcVersion); 55 | 56 | } 57 | catch (ClassCastException e) 58 | { 59 | return false; 60 | } 61 | } 62 | 63 | @Override 64 | public int hashCode() 65 | { 66 | return (side.ordinal() << 8) + type.ordinal() + mcVersion.hashCode(); 67 | } 68 | 69 | @Override 70 | public String toString() 71 | { 72 | return mcVersion + " " + type + " " + side; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/immibis/bon/gui/Reference.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Alex "immibis" Campbell 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 5 | * files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 7 | * Software is furnished to do so, subject to the following conditions: 8 | * 9 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 12 | * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 13 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 14 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | */ 16 | package immibis.bon.gui; 17 | 18 | public class Reference 19 | { 20 | public T val; 21 | 22 | public Reference() 23 | {} 24 | 25 | public Reference(T val) 26 | { 27 | this.val = val; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/immibis/bon/gui/Side.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Alex "immibis" Campbell, bspkrs 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 5 | * files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, 6 | * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 7 | * Software is furnished to do so, subject to the following conditions: 8 | * 9 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | * 11 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 12 | * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 13 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 14 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | */ 16 | package immibis.bon.gui; 17 | 18 | import immibis.bon.NameSet; 19 | 20 | public enum Side 21 | { 22 | Universal(NameSet.Side.UNIVERSAL, "bin/minecraft", new int[] { 2, 0, 1 }), 23 | Client(NameSet.Side.CLIENT, "bin/minecraft", new int[] { 0 }), 24 | Server(NameSet.Side.SERVER, "bin/minecraft_server", new int[] { 1 }); 25 | 26 | private Side(NameSet.Side nsside, String referencePath, int[] side) 27 | { 28 | this.nsside = nsside; 29 | this.referencePath = referencePath; 30 | this.intSide = side; 31 | } 32 | 33 | public final NameSet.Side nsside; 34 | public final String referencePath; 35 | public final int[] intSide; 36 | } 37 | -------------------------------------------------------------------------------- /src/main/resources/bspkrs/mmv/gui/icon/bspkrs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bspkrs/MCPMappingViewer/756b6bd16fcc7bb1eb60fd9b78796cd9aee4277f/src/main/resources/bspkrs/mmv/gui/icon/bspkrs.png -------------------------------------------------------------------------------- /src/main/resources/bspkrs/mmv/gui/icon/bspkrs128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bspkrs/MCPMappingViewer/756b6bd16fcc7bb1eb60fd9b78796cd9aee4277f/src/main/resources/bspkrs/mmv/gui/icon/bspkrs128.png -------------------------------------------------------------------------------- /src/main/resources/bspkrs/mmv/gui/icon/bspkrs16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bspkrs/MCPMappingViewer/756b6bd16fcc7bb1eb60fd9b78796cd9aee4277f/src/main/resources/bspkrs/mmv/gui/icon/bspkrs16.png -------------------------------------------------------------------------------- /src/main/resources/bspkrs/mmv/gui/icon/bspkrs24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bspkrs/MCPMappingViewer/756b6bd16fcc7bb1eb60fd9b78796cd9aee4277f/src/main/resources/bspkrs/mmv/gui/icon/bspkrs24.png -------------------------------------------------------------------------------- /src/main/resources/bspkrs/mmv/gui/icon/bspkrs32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bspkrs/MCPMappingViewer/756b6bd16fcc7bb1eb60fd9b78796cd9aee4277f/src/main/resources/bspkrs/mmv/gui/icon/bspkrs32.png -------------------------------------------------------------------------------- /src/main/resources/bspkrs/mmv/gui/icon/bspkrs48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bspkrs/MCPMappingViewer/756b6bd16fcc7bb1eb60fd9b78796cd9aee4277f/src/main/resources/bspkrs/mmv/gui/icon/bspkrs48.png -------------------------------------------------------------------------------- /src/main/resources/bspkrs/mmv/gui/icon/bspkrs64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bspkrs/MCPMappingViewer/756b6bd16fcc7bb1eb60fd9b78796cd9aee4277f/src/main/resources/bspkrs/mmv/gui/icon/bspkrs64.png --------------------------------------------------------------------------------