├── .gitignore ├── LICENSE.md ├── README.md ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── src └── main ├── java └── team │ └── pepsi │ └── pepsimod │ └── launcher │ ├── ClassLoadingNotifier.java │ ├── FatalError.java │ ├── LauncherMixinLoader.java │ ├── PepsiModLauncher.java │ ├── PepsiModServerManager.java │ ├── classloading │ └── PepsiModClassLoader.java │ ├── packet │ ├── ClientRequest.java │ ├── Packet.java │ ├── PacketDataInput.java │ ├── PacketDataOutput.java │ ├── ServerClose.java │ └── ServerPepsimodSend.java │ ├── resources │ ├── PepsiResourceAdder.java │ ├── PepsiURLConnection.java │ └── PepsiURLStreamHandler.java │ └── util │ ├── CerializableUtils.java │ ├── DataTag.java │ └── PepsimodSent.java └── resources ├── META-INF └── MANIFEST.MF └── mcmod.info /.gitignore: -------------------------------------------------------------------------------- 1 | # eclipse 2 | bin 3 | *.launch 4 | .settings 5 | .metadata 6 | .classpath 7 | .project 8 | 9 | # idea 10 | out 11 | *.ipr 12 | *.iws 13 | *.iml 14 | .idea 15 | classes/ 16 | 17 | # gradle 18 | build 19 | .gradle 20 | 21 | # other 22 | eclipse 23 | run 24 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Adapted from the Wizardry License 2 | 3 | Copyright (c) 2016 Team Pepsi 4 | 5 | Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. 6 | 7 | The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from Team Pepsi. 8 | 9 | Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: Team Pepsi), as well as provide a link to the original project. 10 | 11 | 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 NON INFRINGEMENT. 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. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pepsimodLauncher 2 | 3 | ## DEPRECATED 4 | 5 | The launcher for pepsimod, this downloads classes, decrypts them and uses classloader hackery to make them load. 6 | 7 | Generally speaking, it almost never works correctly, and when it does, it freezes the JVM a lot. I don't **WANT** to try and fix this, as it's super hacky code slammed together by 14-year-old me and I don't even remember exactly why most of it is there, and removing a debug message can sometimes be the difference between a JVM crash and a perfect launch. 8 | 9 | Currently only keeping this repo around for posterity, if anyone ever decides to fix it or use it for another project feel free, so long as I'm credited. 10 | 11 | -- DaPorkchop_, 2 Dec. 2017 12 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * Adapted from the Wizardry License 3 | * 4 | * Copyright (c) 2016 Team Pepsi 5 | * 6 | * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. 7 | * 8 | * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from Team Pepsi. 9 | * 10 | * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: Team Pepsi), as well as provide a link to the original project. 11 | * 12 | * 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 NON INFRINGEMENT. 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. 13 | */ 14 | 15 | buildscript { 16 | repositories { 17 | jcenter() 18 | maven { 19 | name = "forge" 20 | url = "http://files.minecraftforge.net/maven" 21 | } 22 | maven { 23 | name = 'SpongePowered' 24 | url = 'http://repo.spongepowered.org/maven' 25 | } 26 | } 27 | dependencies { 28 | classpath 'net.minecraftforge.gradle:ForgeGradle:2.3-SNAPSHOT' 29 | classpath 'org.spongepowered:mixingradle:0.4-SNAPSHOT' 30 | classpath 'com.github.jengelman.gradle.plugins:shadow:1.2.4' 31 | } 32 | } 33 | 34 | apply plugin: "net.minecraftforge.gradle.forge" 35 | apply plugin: 'org.spongepowered.mixin' 36 | apply plugin: 'com.github.johnrengelman.shadow' 37 | 38 | repositories { 39 | mavenCentral() 40 | maven { 41 | name = 'Jitpack' 42 | url = 'https://jitpack.io' 43 | } 44 | } 45 | 46 | version = "11.1" 47 | group = "net.daporkchop" 48 | archivesBaseName = "pepsimodlauncher" 49 | 50 | sourceCompatibility = targetCompatibility = '1.8' 51 | compileJava { 52 | sourceCompatibility = targetCompatibility = '1.8' 53 | } 54 | 55 | minecraft { 56 | version = "1.12.2-14.23.0.2486" 57 | runDir = "run" 58 | mappings = "snapshot_20170919" 59 | makeObfSourceJar = false 60 | coreMod = "team.pepsi.pepsimod.launcher.LauncherMixinLoader" 61 | } 62 | 63 | repositories { 64 | maven { 65 | name = 'spongepowered-repo' 66 | url = 'http://repo.spongepowered.org/maven/' 67 | } 68 | maven { 69 | name = 'marfgamer' 70 | url = 'https://raw.githubusercontent.com/JRakNet/MavenRepository/master' 71 | } 72 | mavenCentral() 73 | } 74 | 75 | dependencies { 76 | compile("org.spongepowered:mixin:0.7.5-SNAPSHOT") { 77 | exclude module: "launchwrapper" 78 | } 79 | compile 'com.github.Team-Pepsi:pepsimod-common:ff7233b5df31e96ff437242794a43333ad8e0a94' 80 | compile 'io.netty:netty-handler:4.1.2.Final' 81 | compile 'org.jhardware:jHardware:0.8.4' 82 | } 83 | 84 | processResources { 85 | // this will ensure that this task is redone when the versions change. 86 | inputs.property "version", project.version 87 | inputs.property "mcversion", project.minecraft.version 88 | 89 | // replace stuff in mcmod.info, nothing else 90 | from(sourceSets.main.resources.srcDirs) { 91 | include "mcmod.info" 92 | 93 | // replace version and mcversion 94 | expand "version": project.version, "mcversion": project.minecraft.version 95 | } 96 | 97 | // copy everything else, thats not the mcmod.info 98 | from(sourceSets.main.resources.srcDirs) { 99 | exclude "mcmod.info" 100 | } 101 | 102 | // move _at.cfg into META-INF 103 | rename '(.+_at.cfg)', 'META-INF/$1' 104 | } 105 | 106 | mixin { 107 | defaultObfuscationEnv searge 108 | add sourceSets.main, "mixins.pepsimod.refmap.json" 109 | } 110 | 111 | reobf { 112 | shadowJar { 113 | mappingType = 'SEARGE' 114 | classpath = sourceSets.main.compileClasspath 115 | } 116 | } 117 | 118 | shadowJar { 119 | dependencies { 120 | include(dependency('org.spongepowered:mixin')) 121 | include(dependency('com.github.Team-Pepsi:pepsimod-common')) 122 | include(dependency('org.jhardware:jHardware')) 123 | include(dependency('com.profesorfalken:WMI4Java')) 124 | include(dependency('com.profesorfalken:jSensors')) 125 | include(dependency('com.profesorfalken:jPowerShell')) 126 | include(dependency('net.java.dev.jna:jna')) 127 | include(dependency('org.slf4j:slf4j-simple')) 128 | include(dependency('org.slf4j:slf4j-api')) 129 | include(dependency('org.springframework.security:spring-security-crypto')) 130 | include(dependency('org.springframework:spring-core')) 131 | //include(dependency('net.marfgamer:jraknet')) 132 | //include(dependency('joda-time:joda-time')) 133 | include(dependency('io.netty:netty-handler')) 134 | include(dependency('io.netty:netty-buffer')) 135 | include(dependency('io.netty:netty-common')) 136 | include(dependency('io.netty:netty-transport')) 137 | include(dependency('io.netty:netty-resolver')) 138 | include(dependency('io.netty:netty-codec')) 139 | } 140 | exclude 'dummyThing' 141 | exclude 'LICENSE.txt' 142 | classifier = 'full' 143 | } 144 | 145 | build.dependsOn(shadowJar) 146 | 147 | jar { 148 | manifest { 149 | attributes( 150 | "MixinConfigs": 'mixins.pepsimod.json', 151 | 'FMLCorePluginContainsFMLMod': 'true', 152 | "tweakClass": 'org.spongepowered.asm.launch.MixinTweaker', 153 | "TweakOrder": 0, 154 | 'FMLCorePlugin': 'team.pepsi.pepsimod.launcher.LauncherMixinLoader', 155 | 'FMLAT': 'pepsimod_at.cfg', 156 | 'ForceLoadAsMod': 'true' 157 | ) 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Sets default memory used for gradle commands. Can be overridden by user or command line properties. 2 | # This is required to provide enough memory for the Minecraft decompilation process. 3 | org.gradle.jvmargs=-Xmx3G 4 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Team-Pepsi/pepsimodLauncher/6af87f822fc15b303521c7cbcd68f3a49852b2df/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sat May 20 01:25:38 BST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.14-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /src/main/java/team/pepsi/pepsimod/launcher/ClassLoadingNotifier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Adapted from the Wizardry License 3 | * 4 | * Copyright (c) 2016 Team Pepsi 5 | * 6 | * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. 7 | * 8 | * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from Team Pepsi. 9 | * 10 | * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: Team Pepsi), as well as provide a link to the original project. 11 | * 12 | * 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 NON INFRINGEMENT. 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. 13 | */ 14 | 15 | package team.pepsi.pepsimod.launcher; 16 | 17 | import net.minecraft.launchwrapper.IClassTransformer; 18 | 19 | public class ClassLoadingNotifier implements IClassTransformer { 20 | public byte[] transform(String name, String transformedName, byte[] basicClass) { 21 | //FMLLog.log.info("Class loading: " + transformedName); 22 | return basicClass; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/team/pepsi/pepsimod/launcher/FatalError.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Adapted from the Wizardry License 3 | * 4 | * Copyright (c) 2016 Team Pepsi 5 | * 6 | * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. 7 | * 8 | * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from Team Pepsi. 9 | * 10 | * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: Team Pepsi), as well as provide a link to the original project. 11 | * 12 | * 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 NON INFRINGEMENT. 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. 13 | */ 14 | 15 | package team.pepsi.pepsimod.launcher; 16 | 17 | public class FatalError extends Error { 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/team/pepsi/pepsimod/launcher/LauncherMixinLoader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Adapted from the Wizardry License 3 | * 4 | * Copyright (c) 2016 Team Pepsi 5 | * 6 | * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. 7 | * 8 | * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from Team Pepsi. 9 | * 10 | * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: Team Pepsi), as well as provide a link to the original project. 11 | * 12 | * 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 NON INFRINGEMENT. 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. 13 | */ 14 | 15 | package team.pepsi.pepsimod.launcher; 16 | 17 | import net.minecraft.launchwrapper.Launch; 18 | import net.minecraft.launchwrapper.LaunchClassLoader; 19 | import net.minecraftforge.fml.common.FMLLog; 20 | import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin; 21 | import org.spongepowered.asm.launch.MixinBootstrap; 22 | import org.spongepowered.asm.mixin.Mixins; 23 | import sun.misc.Unsafe; 24 | import team.pepsi.pepsimod.launcher.classloading.PepsiModClassLoader; 25 | import team.pepsi.pepsimod.launcher.resources.PepsiResourceAdder; 26 | import team.pepsi.pepsimod.launcher.util.PepsimodSent; 27 | 28 | import javax.annotation.Nullable; 29 | import javax.swing.*; 30 | import java.awt.*; 31 | import java.lang.reflect.Field; 32 | import java.lang.reflect.InvocationTargetException; 33 | import java.lang.reflect.Method; 34 | import java.net.URL; 35 | import java.util.ArrayList; 36 | import java.util.Map; 37 | 38 | public class LauncherMixinLoader implements IFMLLoadingPlugin { 39 | public static boolean isObfuscatedEnvironment = false; 40 | public static PepsiModClassLoader classLoader; 41 | public static ArrayList loadingClasses = new ArrayList<>(); 42 | public static JDialog dialog; 43 | public static JLabel label = new JLabel("...................................................................................................................."); 44 | public Object coremod; 45 | 46 | public LauncherMixinLoader() { 47 | JFrame f = new JFrame(); 48 | dialog = new JDialog(f, "pepsimod", true); 49 | dialog.setModal(false); 50 | dialog.setLayout(new FlowLayout()); 51 | dialog.add(label); 52 | dialog.pack(); 53 | dialog.setLocationRelativeTo(null); 54 | dialog.setVisible(true); 55 | try { 56 | PepsiModServerManager.downloadPepsiMod(); 57 | 58 | FMLLog.info("1"); 59 | classLoader = new PepsiModClassLoader(new URL[0], null, PepsimodSent.INSTANCE.classes); 60 | 61 | FMLLog.info("2"); 62 | Field parent = ClassLoader.class.getDeclaredField("parent"); 63 | FMLLog.info("3"); 64 | Unsafe unsafe = getUnsafe(); 65 | FMLLog.info("4"); 66 | long offset = unsafe.objectFieldOffset(parent); 67 | FMLLog.info("5"); 68 | FMLLog.info(getClass().getClassLoader().getClass().getCanonicalName()); 69 | if (this.getClass().getClassLoader().getParent() != null) { 70 | unsafe.putObject(this.getClass().getClassLoader().getParent(), offset, classLoader); 71 | } else { 72 | FMLLog.info("Not setting loader's parent"); 73 | //unsafe.putObject(this.getClass().getClassLoader(), offset, classLoader); 74 | ClassLoader loader = Launch.classLoader; 75 | while (getParent(loader) != null) { 76 | FMLLog.log.info(loader.getClass().getCanonicalName()); 77 | loader = getParent(loader); 78 | } 79 | unsafe.putObject(loader, unsafe.fieldOffset(ClassLoader.class.getDeclaredField("parent")), classLoader); 80 | } 81 | FMLLog.info("6"); 82 | unsafe.putObject(Launch.classLoader, offset, new PepsiResourceAdder()); 83 | 84 | FMLLog.info("7"); 85 | Field resourceCache = LaunchClassLoader.class.getDeclaredField("resourceCache"); 86 | FMLLog.info("8"); 87 | resourceCache.setAccessible(true); 88 | FMLLog.info("9"); 89 | Map classCache = (Map) resourceCache.get(Launch.classLoader); 90 | FMLLog.info("10"); 91 | FMLLog.log.info("Initial size: " + classCache.size()); 92 | FMLLog.info("11"); 93 | for (Map.Entry entry : PepsimodSent.INSTANCE.classes.entrySet()) { 94 | classCache.put(entry.getKey(), entry.getValue()); 95 | } 96 | FMLLog.info("12"); 97 | FMLLog.log.info("Size after: " + ((Map) resourceCache.get(Launch.classLoader)).size()); 98 | 99 | FMLLog.log.info("ClassLoader heirachy:"); 100 | ClassLoader loader = Launch.classLoader; 101 | while (getParent(loader) != null) { 102 | FMLLog.log.info(loader.getClass().getCanonicalName()); 103 | loader = getParent(loader); 104 | } 105 | FMLLog.log.info(loader.getClass().getCanonicalName()); 106 | 107 | FMLLog.log.info("\n\n\nPepsiMod Mixin init\n\n"); 108 | MixinBootstrap.init(); 109 | Mixins.addConfiguration("mixins.pepsimod.json"); 110 | Mixins.addConfiguration("mixins.pepsimod.wdl.json"); 111 | FMLLog.info("13"); 112 | coremod = Class.forName("net.daporkchop.pepsimod.PepsiModMixinLoader").newInstance(); 113 | FMLLog.info("14"); 114 | } catch (Throwable t) { 115 | t.printStackTrace(); 116 | System.out.println("FATAL ERROR IN PEPSIMOD LAUNCHER, SYSTEM WILL EXIT NOW!!!"); 117 | if (true) { 118 | throw new FatalError(); 119 | } 120 | Runtime.getRuntime().exit(0); 121 | } 122 | dialog.setVisible(false); 123 | dialog.dispose(); 124 | dialog = null; 125 | } 126 | 127 | public static Unsafe getUnsafe() { 128 | try { 129 | Field f = Unsafe.class.getDeclaredField("theUnsafe"); 130 | f.setAccessible(true); 131 | return (Unsafe) f.get(null); 132 | } catch (Exception e) { 133 | e.printStackTrace(); 134 | Runtime.getRuntime().exit(928273); 135 | } 136 | 137 | return null; 138 | } 139 | 140 | public static Class tryLoadingClassAsMainLoader(String name) throws ClassNotFoundException { 141 | if (loadingClasses.contains(name)) { 142 | throw new ClassNotFoundException("CLASS NOT LOADED ON SECOND ITERATION! " + name); 143 | } 144 | loadingClasses.add(name); 145 | Class toReturn = null; 146 | toReturn = Launch.classLoader.loadClass(name); 147 | if (toReturn == null) { 148 | FMLLog.log.info("Unable to load class " + name + " with Launch.classLoader"); 149 | toReturn = LaunchClassLoader.class.getClassLoader().loadClass(name); 150 | } 151 | loadingClasses.remove(name); 152 | if (toReturn == null) { 153 | FMLLog.log.info("Failed to load class " + name); 154 | throw new NoClassDefFoundError("unable to load class"); 155 | } 156 | return toReturn; 157 | } 158 | 159 | @Override 160 | public String[] getASMTransformerClass() { 161 | return new String[]{"team.pepsi.pepsimod.launcher.ClassLoadingNotifier"}; 162 | } 163 | 164 | @Override 165 | public String getModContainerClass() { 166 | return null; 167 | } 168 | 169 | @Nullable 170 | @Override 171 | public String getSetupClass() { 172 | return null; 173 | } 174 | 175 | @Override 176 | public void injectData(Map data) { 177 | isObfuscatedEnvironment = (boolean) (Boolean) data.get("runtimeDeobfuscationEnabled"); 178 | try { 179 | Method m = Class.forName("net.daporkchop.pepsimod.PepsiModMixinLoader").getDeclaredMethod("injectData", Map.class); 180 | m.invoke(coremod, data); 181 | } catch (IllegalAccessException | InvocationTargetException | ClassNotFoundException | NoSuchMethodException e) { 182 | throw new IllegalStateException(e.getCause()); 183 | } 184 | } 185 | 186 | @Override 187 | public String getAccessTransformerClass() { 188 | try { 189 | Method m = Class.forName("net.daporkchop.pepsimod.PepsiModMixinLoader").getDeclaredMethod("getAccessTransformerClass"); 190 | m.invoke(coremod); 191 | } catch (IllegalAccessException | InvocationTargetException | ClassNotFoundException | NoSuchMethodException e) { 192 | throw new IllegalStateException(e.getCause()); 193 | } 194 | return ""; 195 | } 196 | 197 | public ClassLoader getParent(ClassLoader loader) { 198 | if (loader instanceof LaunchClassLoader) { 199 | try { 200 | Field f = LaunchClassLoader.class.getDeclaredField("parent"); 201 | f.setAccessible(true); 202 | return (ClassLoader) f.get(loader); 203 | } catch (Exception e) { 204 | e.printStackTrace(); 205 | } 206 | } 207 | 208 | return loader.getParent(); 209 | } 210 | } 211 | -------------------------------------------------------------------------------- /src/main/java/team/pepsi/pepsimod/launcher/PepsiModLauncher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Adapted from the Wizardry License 3 | * 4 | * Copyright (c) 2016 Team Pepsi 5 | * 6 | * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. 7 | * 8 | * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from Team Pepsi. 9 | * 10 | * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: Team Pepsi), as well as provide a link to the original project. 11 | * 12 | * 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 NON INFRINGEMENT. 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. 13 | */ 14 | 15 | package team.pepsi.pepsimod.launcher; 16 | 17 | import net.minecraftforge.fml.common.Mod; 18 | import net.minecraftforge.fml.common.event.FMLConstructionEvent; 19 | import net.minecraftforge.fml.common.event.FMLInitializationEvent; 20 | import net.minecraftforge.fml.common.event.FMLPostInitializationEvent; 21 | import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; 22 | import org.apache.logging.log4j.Logger; 23 | import team.pepsi.pepsimod.launcher.util.PepsimodSent; 24 | 25 | import java.lang.reflect.InvocationTargetException; 26 | import java.lang.reflect.Method; 27 | import java.util.HashMap; 28 | 29 | @Mod(name = "pepsimod", modid = "pepsimod", version = "0.1") 30 | public class PepsiModLauncher { 31 | public static Object pepsimodInstance; 32 | public static Logger logger; 33 | 34 | public PepsiModLauncher() { 35 | 36 | } 37 | 38 | @Mod.EventHandler 39 | public void construct(FMLConstructionEvent event) { 40 | try { 41 | pepsimodInstance = Class.forName("net.daporkchop.pepsimod.PepsiMod").newInstance(); 42 | } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) { 43 | //can't happen 44 | throw new IllegalStateException(e.getCause()); 45 | } 46 | System.out.println("FMLConstructionEvent"); 47 | } 48 | 49 | @Mod.EventHandler 50 | public void preInit(FMLPreInitializationEvent event) { 51 | logger = event.getModLog(); 52 | logger.info("FMLPreInitializationEvent"); 53 | try { 54 | Method m = Class.forName("net.daporkchop.pepsimod.PepsiMod").getDeclaredMethod("preInit", FMLPreInitializationEvent.class); 55 | m.invoke(pepsimodInstance, event); 56 | } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { 57 | //can't happen 58 | throw new IllegalStateException(e.getCause()); 59 | } 60 | } 61 | 62 | @Mod.EventHandler 63 | public void init(FMLInitializationEvent event) { 64 | logger.info("FMLInitializationEvent"); 65 | try { 66 | Method m = Class.forName("net.daporkchop.pepsimod.PepsiMod").getDeclaredMethod("init", FMLInitializationEvent.class); 67 | m.invoke(pepsimodInstance, event); 68 | } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { 69 | //can't happen 70 | throw new IllegalStateException(e.getCause()); 71 | } 72 | } 73 | 74 | @Mod.EventHandler 75 | public void postInit(FMLPostInitializationEvent event) { 76 | logger.info("FMLPostInitializationEvent"); 77 | try { 78 | Method m = Class.forName("net.daporkchop.pepsimod.util.ImageUtils").getDeclaredMethod("init", HashMap.class); 79 | m.invoke(null, PepsimodSent.INSTANCE.assets); 80 | m = Class.forName("net.daporkchop.pepsimod.PepsiMod").getDeclaredMethod("postInit", FMLPostInitializationEvent.class); 81 | m.invoke(pepsimodInstance, event); 82 | } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { 83 | //can't happen 84 | throw new IllegalStateException(e.getCause()); 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/team/pepsi/pepsimod/launcher/PepsiModServerManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Adapted from the Wizardry License 3 | * 4 | * Copyright (c) 2016 Team Pepsi 5 | * 6 | * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. 7 | * 8 | * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from Team Pepsi. 9 | * 10 | * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: Team Pepsi), as well as provide a link to the original project. 11 | * 12 | * 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 NON INFRINGEMENT. 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. 13 | */ 14 | 15 | package team.pepsi.pepsimod.launcher; 16 | 17 | import io.netty.bootstrap.Bootstrap; 18 | import io.netty.buffer.ByteBuf; 19 | import io.netty.channel.*; 20 | import io.netty.channel.nio.NioEventLoopGroup; 21 | import io.netty.channel.socket.SocketChannel; 22 | import io.netty.channel.socket.nio.NioSocketChannel; 23 | import io.netty.handler.codec.LengthFieldBasedFrameDecoder; 24 | import io.netty.handler.codec.LengthFieldPrepender; 25 | import net.minecraftforge.common.ForgeVersion; 26 | import net.minecraftforge.fml.common.FMLCommonHandler; 27 | import net.minecraftforge.fml.common.FMLLog; 28 | import org.jutils.jhardware.HardwareInfo; 29 | import org.jutils.jhardware.model.*; 30 | import team.pepsi.pepsimod.common.util.CryptUtils; 31 | import team.pepsi.pepsimod.common.util.Zlib; 32 | import team.pepsi.pepsimod.launcher.packet.ClientRequest; 33 | import team.pepsi.pepsimod.launcher.packet.Packet; 34 | import team.pepsi.pepsimod.launcher.packet.ServerClose; 35 | import team.pepsi.pepsimod.launcher.packet.ServerPepsimodSend; 36 | import team.pepsi.pepsimod.launcher.util.CerializableUtils; 37 | import team.pepsi.pepsimod.launcher.util.DataTag; 38 | import team.pepsi.pepsimod.launcher.util.PepsimodSent; 39 | 40 | import javax.swing.*; 41 | import java.io.File; 42 | import java.lang.reflect.Field; 43 | import java.lang.reflect.Modifier; 44 | import java.security.Permission; 45 | import java.security.PermissionCollection; 46 | import java.util.HashMap; 47 | import java.util.Map; 48 | 49 | public class PepsiModServerManager { 50 | public static final int protocol = 5; 51 | public static DataTag tag = new DataTag(new File(DataTag.HOME_FOLDER.getPath() + File.separatorChar + "pepsimodauth.dat")); 52 | public static String hwid = null; 53 | public static boolean errored = false; 54 | public static boolean wrongPass = false; 55 | public static String newPassword = null; 56 | static boolean processedResponse = false; 57 | 58 | static { 59 | LauncherMixinLoader.label.setText("Removing cryptography restrictions..."); 60 | removeCryptographyRestrictions(); 61 | LauncherMixinLoader.label.setText("Generating HWID..."); 62 | getHWID(); 63 | } 64 | 65 | public static void promptForCredentials() { 66 | JLabel label_login = new JLabel("Username:"); 67 | JTextField login = new JTextField(); 68 | 69 | JLabel label_password = new JLabel("Password:"); 70 | JPasswordField password = new JPasswordField(); 71 | 72 | Object[] array = {label_login, login, label_password, password}; 73 | 74 | if (LauncherMixinLoader.dialog != null) { 75 | LauncherMixinLoader.dialog.setVisible(false); 76 | } 77 | int res = JOptionPane.showConfirmDialog(null, array, "Login", 78 | JOptionPane.OK_OPTION, 79 | JOptionPane.PLAIN_MESSAGE); 80 | if (res != JOptionPane.YES_OPTION) { 81 | FMLCommonHandler.instance().exitJava(93287, true); 82 | } 83 | tag.setString("username", login.getText()); 84 | tag.setString("password", password.getText()); 85 | tag.save(); 86 | if (LauncherMixinLoader.dialog != null) { 87 | LauncherMixinLoader.dialog.setVisible(true); 88 | } 89 | } 90 | 91 | public static PepsimodSent decrypt(ServerPepsimodSend send) { 92 | LauncherMixinLoader.label.setText("Decrypting data..."); 93 | byte[] currentState = send.classes; 94 | currentState = Zlib.inflate(currentState); 95 | Object decrypted; 96 | try { 97 | currentState = CryptUtils.decrypt(currentState, getPassword()); 98 | if (currentState == null) { 99 | return null; 100 | } 101 | decrypted = CerializableUtils.fromBytes(currentState); 102 | } catch (Exception e) { 103 | LauncherMixinLoader.dialog.setVisible(false); 104 | JOptionPane.showMessageDialog(null, "Invalid password!", "pepsimod error", JOptionPane.OK_OPTION); 105 | return null; 106 | } 107 | HashMap classes = (HashMap) decrypted; 108 | currentState = send.assets; 109 | currentState = Zlib.inflate(currentState); 110 | try { 111 | currentState = CryptUtils.decrypt(currentState, getPassword()); 112 | if (currentState == null) { 113 | return null; 114 | } 115 | decrypted = CerializableUtils.fromBytes(currentState); 116 | } catch (Exception e) { 117 | LauncherMixinLoader.dialog.setVisible(false); 118 | JOptionPane.showMessageDialog(null, "Invalid password!", "pepsimod error", JOptionPane.OK_OPTION); 119 | return null; 120 | } 121 | HashMap assets = (HashMap) decrypted; 122 | for (Map.Entry entry : classes.entrySet()) { 123 | classes.put(entry.getKey(), Zlib.inflate(entry.getValue())); //inflate everything 124 | } 125 | for (Map.Entry entry : assets.entrySet()) { 126 | assets.put(entry.getKey(), Zlib.inflate(entry.getValue())); //inflate everything 127 | } 128 | return new PepsimodSent(classes, assets, send.config); 129 | } 130 | 131 | private static boolean handleClose(ServerClose close) { 132 | if (close.hard) { 133 | FMLLog.log.info(close.message); 134 | if (LauncherMixinLoader.dialog != null) { 135 | LauncherMixinLoader.dialog.setVisible(false); 136 | } 137 | JOptionPane.showMessageDialog(null, close.message, "pepsimod error", JOptionPane.OK_OPTION); 138 | forceShutdown(); 139 | return false; 140 | } else { 141 | JOptionPane.showMessageDialog(null, close.message, "pepsimod error", JOptionPane.OK_OPTION); 142 | return true; 143 | } 144 | } 145 | 146 | public static PepsimodSent downloadPepsiMod() { 147 | errored = false; 148 | wrongPass = false; 149 | processedResponse = false; 150 | FMLLog.log.info("Preparing..."); 151 | LauncherMixinLoader.label.setText("Communicating with pepsimod server..."); 152 | EventLoopGroup group = new NioEventLoopGroup(); 153 | try { 154 | Bootstrap bootstrap = new Bootstrap().group(group).channel(NioSocketChannel.class).handler(new ChannelInitializer() { 155 | @Override 156 | public void initChannel(SocketChannel ch) throws Exception { 157 | FMLLog.log.info("initialized channel"); 158 | ch.pipeline().addLast("frameDecoder", new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4)); 159 | ch.pipeline().addLast("frameEncoder", new LengthFieldPrepender(4)); 160 | ch.pipeline().addLast(new ChannelInboundHandlerAdapter() { 161 | @Override 162 | public void channelRead(ChannelHandlerContext ctx, Object msg) { 163 | FMLLog.log.info("Read from channel"); 164 | Packet packet = new Packet((ByteBuf) msg); 165 | packet.decode(); 166 | FMLLog.log.info("Handling packet ID " + packet.getId()); 167 | if (packet.getId() == 1) { 168 | wrongPass = false; 169 | ServerPepsimodSend pepsimodSend = new ServerPepsimodSend(packet.buffer); 170 | pepsimodSend.decode(); 171 | FMLLog.log.info("Class size: " + pepsimodSend.classes.length + " bytes"); 172 | if (decrypt(pepsimodSend) == null) { 173 | wrongPass = true; 174 | } else { 175 | FMLLog.log.info("Successfully decrypted pepsimod!"); 176 | ctx.close(); 177 | } 178 | } else if (packet.getId() == 0) { 179 | ServerClose close = new ServerClose(packet.buffer); 180 | close.decode(); 181 | if (handleClose(close)) { 182 | wrongPass = true; 183 | } else { 184 | errored = true; 185 | } 186 | } 187 | processedResponse = true; 188 | } 189 | }); 190 | } 191 | }); 192 | FMLLog.log.info("Created bootstrap"); 193 | Channel channel = bootstrap.connect("home.daporkchop.net", 48273).sync().channel(); 194 | FMLLog.log.info("Connected!"); 195 | ClientRequest request = new ClientRequest(); 196 | request.hwid = getHWID(); 197 | request.nextRequest = 0; 198 | request.protocol = protocol; 199 | request.username = getUsername(); 200 | request.version = getVersion(); 201 | request.password = ""; 202 | request.config = ""; 203 | request.encode(); 204 | channel.writeAndFlush(request.buffer); 205 | FMLLog.log.info("sent!"); 206 | while (!processedResponse) { 207 | if (processedResponse) { 208 | break; 209 | } else { 210 | Thread.sleep(1000); 211 | FMLLog.log.info("Waiting..."); 212 | } 213 | } 214 | } catch (Exception e) { 215 | e.printStackTrace(); 216 | } finally { 217 | group.shutdownGracefully(); 218 | } 219 | 220 | if (errored) { 221 | forceShutdown(); 222 | } else if (wrongPass) { 223 | promptForCredentials(); 224 | return downloadPepsiMod(); 225 | } 226 | FMLLog.log.info("Done!"); 227 | 228 | return PepsimodSent.INSTANCE; 229 | } 230 | 231 | public static String setPassword() { 232 | JLabel label_password = new JLabel("New password:"); 233 | JPasswordField password = new JPasswordField(); 234 | 235 | Object[] array = {label_password, password}; 236 | 237 | if (LauncherMixinLoader.dialog != null) { 238 | LauncherMixinLoader.dialog.setVisible(false); 239 | } 240 | int res = JOptionPane.showConfirmDialog(null, array, "Change password", JOptionPane.OK_OPTION, JOptionPane.PLAIN_MESSAGE); 241 | if (res != JOptionPane.YES_OPTION) { 242 | return null; 243 | } 244 | 245 | return setPassword(password.getText()); 246 | } 247 | 248 | public static String setPassword(String toSet) { 249 | errored = false; 250 | wrongPass = false; 251 | processedResponse = false; 252 | FMLLog.log.info("Preparing..."); 253 | LauncherMixinLoader.label.setText("Communicating with pepsimod server..."); 254 | EventLoopGroup group = new NioEventLoopGroup(); 255 | try { 256 | Bootstrap bootstrap = new Bootstrap().group(group).channel(NioSocketChannel.class).handler(new ChannelInitializer() { 257 | @Override 258 | public void initChannel(SocketChannel ch) throws Exception { 259 | System.out.println("initialized channel"); 260 | ch.pipeline().addLast("frameDecoder", new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4)); 261 | ch.pipeline().addLast("frameEncoder", new LengthFieldPrepender(4)); 262 | ch.pipeline().addLast(new ChannelInboundHandlerAdapter() { 263 | @Override 264 | public void channelRead(ChannelHandlerContext ctx, Object msg) { 265 | System.out.println("Read from channel"); 266 | Packet packet = new Packet((ByteBuf) msg); 267 | packet.decode(); 268 | System.out.println("Handling packet ID " + packet.getId()); 269 | if (packet.getId() == 0) { 270 | ServerClose close = new ServerClose(packet.buffer); 271 | close.decode(); 272 | if (close.message.toLowerCase().startsWith("success")) { 273 | ctx.close(); 274 | return; 275 | } 276 | if (handleClose(close)) { 277 | promptForCredentials(); 278 | } else { 279 | forceShutdown(); 280 | } 281 | ctx.close(); 282 | } 283 | } 284 | }); 285 | } 286 | }); 287 | FMLLog.log.info("Created bootstrap"); 288 | Channel channel = bootstrap.connect("home.daporkchop.net", 48273).sync().channel(); 289 | FMLLog.log.info("Connected!"); 290 | ClientRequest request = new ClientRequest(); 291 | request.hwid = getHWID(); 292 | request.nextRequest = 1; 293 | request.protocol = protocol; 294 | request.username = getUsername(); 295 | request.version = getVersion(); 296 | request.password = toSet; 297 | request.config = ""; 298 | request.encode(); 299 | channel.writeAndFlush(request.buffer); 300 | FMLLog.log.info("sent!"); 301 | } catch (Exception e) { 302 | e.printStackTrace(); 303 | } finally { 304 | group.shutdownGracefully(); 305 | } 306 | 307 | tag.setString("password", toSet); 308 | tag.save(); 309 | FMLLog.log.info("Done!"); 310 | 311 | return newPassword; 312 | } 313 | 314 | public static String setConfig(String toSet) { 315 | errored = false; 316 | wrongPass = false; 317 | processedResponse = false; 318 | FMLLog.log.info("Preparing..."); 319 | LauncherMixinLoader.label.setText("Communicating with pepsimod server..."); 320 | EventLoopGroup group = new NioEventLoopGroup(); 321 | try { 322 | Bootstrap bootstrap = new Bootstrap().group(group).channel(NioSocketChannel.class).handler(new ChannelInitializer() { 323 | @Override 324 | public void initChannel(SocketChannel ch) throws Exception { 325 | System.out.println("initialized channel"); 326 | ch.pipeline().addLast("frameDecoder", new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4)); 327 | ch.pipeline().addLast("frameEncoder", new LengthFieldPrepender(4)); 328 | ch.pipeline().addLast(new ChannelInboundHandlerAdapter() { 329 | @Override 330 | public void channelRead(ChannelHandlerContext ctx, Object msg) { 331 | System.out.println("Read from channel"); 332 | Packet packet = new Packet((ByteBuf) msg); 333 | packet.decode(); 334 | System.out.println("Handling packet ID " + packet.getId()); 335 | if (packet.getId() == 0) { 336 | ServerClose close = new ServerClose(packet.buffer); 337 | close.decode(); 338 | if (close.message.toLowerCase().startsWith("success")) { 339 | ctx.close(); 340 | return; 341 | } 342 | if (handleClose(close)) { 343 | promptForCredentials(); 344 | } else { 345 | forceShutdown(); 346 | } 347 | ctx.close(); 348 | } 349 | } 350 | }); 351 | } 352 | }); 353 | FMLLog.log.info("Created bootstrap"); 354 | Channel channel = bootstrap.connect("home.daporkchop.net", 48273).sync().channel(); 355 | FMLLog.log.info("Connected!"); 356 | ClientRequest request = new ClientRequest(); 357 | request.hwid = getHWID(); 358 | request.nextRequest = 2; 359 | request.protocol = protocol; 360 | request.username = getUsername(); 361 | request.version = getVersion(); 362 | request.password = ""; 363 | request.config = toSet; 364 | request.encode(); 365 | channel.writeAndFlush(request.buffer); 366 | FMLLog.log.info("sent!"); 367 | } catch (Exception e) { 368 | e.printStackTrace(); 369 | } finally { 370 | group.shutdownGracefully(); 371 | } 372 | 373 | tag.setString("password", toSet); 374 | tag.save(); 375 | FMLLog.log.info("Done!"); 376 | 377 | return newPassword; 378 | } 379 | 380 | public static String getUsername() { 381 | if (tag.getString("username", null) == null) { 382 | promptForCredentials(); 383 | } 384 | return tag.getString("username"); 385 | } 386 | 387 | public static String getPassword() { 388 | return tag.getString("password"); 389 | } 390 | 391 | public static String getHWID() { 392 | if (hwid != null) { 393 | return hwid; 394 | } 395 | ProcessorInfo info = HardwareInfo.getProcessorInfo(); 396 | MotherboardInfo info2 = HardwareInfo.getMotherboardInfo(); 397 | GraphicsCardInfo info3 = HardwareInfo.getGraphicsCardInfo(); 398 | OSInfo info5 = HardwareInfo.getOSInfo(); 399 | GraphicsCard card = info3.getGraphicsCards().size() > 0 ? info3.getGraphicsCards().get(0) : null; 400 | hwid = info.getModelName() + info.getModel() + info2.getName() + (card != null ? card.getName() : "nonce") + info5.getName(); 401 | return hwid; 402 | } 403 | 404 | private static void removeCryptographyRestrictions() { 405 | if (!isRestrictedCryptography()) { 406 | FMLLog.log.info("Cryptography restrictions removal not needed"); 407 | return; 408 | } 409 | try { 410 | /* 411 | * Do the following, but with reflection to bypass access checks: 412 | * 413 | * JceSecurity.isRestricted = false; 414 | * JceSecurity.defaultPolicy.perms.clear(); 415 | * JceSecurity.defaultPolicy.add(CryptoAllPermission.INSTANCE); 416 | */ 417 | final Class jceSecurity = Class.forName("javax.crypto.JceSecurity"); 418 | final Class cryptoPermissions = Class.forName("javax.crypto.CryptoPermissions"); 419 | final Class cryptoAllPermission = Class.forName("javax.crypto.CryptoAllPermission"); 420 | 421 | final Field isRestrictedField = jceSecurity.getDeclaredField("isRestricted"); 422 | isRestrictedField.setAccessible(true); 423 | final Field modifiersField = Field.class.getDeclaredField("modifiers"); 424 | modifiersField.setAccessible(true); 425 | modifiersField.setInt(isRestrictedField, isRestrictedField.getModifiers() & ~Modifier.FINAL); 426 | isRestrictedField.set(null, false); 427 | 428 | final Field defaultPolicyField = jceSecurity.getDeclaredField("defaultPolicy"); 429 | defaultPolicyField.setAccessible(true); 430 | final PermissionCollection defaultPolicy = (PermissionCollection) defaultPolicyField.get(null); 431 | 432 | final Field perms = cryptoPermissions.getDeclaredField("perms"); 433 | perms.setAccessible(true); 434 | ((Map) perms.get(defaultPolicy)).clear(); 435 | 436 | final Field instance = cryptoAllPermission.getDeclaredField("INSTANCE"); 437 | instance.setAccessible(true); 438 | defaultPolicy.add((Permission) instance.get(null)); 439 | 440 | FMLLog.log.info("Successfully removed cryptography restrictions"); 441 | } catch (final Exception e) { 442 | FMLLog.log.info("Failed to remove cryptography restrictions"); 443 | } 444 | } 445 | 446 | private static boolean isRestrictedCryptography() { 447 | // This matches Oracle Java 7 and 8, but not Java 9 or OpenJDK. 448 | final String name = System.getProperty("java.runtime.name"); 449 | final String ver = System.getProperty("java.version"); 450 | return name != null && name.equals("Java(TM) SE Runtime Environment") 451 | && ver != null && (ver.startsWith("1.7") || ver.startsWith("1.8")); 452 | } 453 | 454 | public static void forceShutdown() { 455 | try { 456 | Runtime.class.getDeclaredMethod("exit", int.class).invoke(Runtime.getRuntime(), 1); 457 | } catch (Exception e) { 458 | e.printStackTrace(); 459 | } 460 | try { 461 | Runtime.class.getDeclaredMethod("halt", int.class).invoke(Runtime.getRuntime(), 3); 462 | } catch (Exception e) { 463 | e.printStackTrace(); 464 | } 465 | try { 466 | FMLCommonHandler.instance().exitJava(1, true); 467 | } catch (Exception e) { 468 | e.printStackTrace(); 469 | } 470 | try { 471 | FMLCommonHandler.instance().exitJava(3, false); 472 | } catch (Exception e) { 473 | e.printStackTrace(); 474 | } 475 | throw new NullPointerException("xd let's crash the game since forceshutdown didn't work"); 476 | } 477 | 478 | public static String getVersion() { 479 | try { 480 | Field f = ForgeVersion.class.getDeclaredField("mcVersion"); 481 | String version = "pepsimod-" + f.get(null); 482 | FMLLog.log.info(version); 483 | return version; 484 | } catch (Exception e) { 485 | e.printStackTrace(); 486 | throw new IllegalStateException(e); 487 | } 488 | } 489 | } 490 | -------------------------------------------------------------------------------- /src/main/java/team/pepsi/pepsimod/launcher/classloading/PepsiModClassLoader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Adapted from the Wizardry License 3 | * 4 | * Copyright (c) 2016 Team Pepsi 5 | * 6 | * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. 7 | * 8 | * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from Team Pepsi. 9 | * 10 | * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: Team Pepsi), as well as provide a link to the original project. 11 | * 12 | * 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 NON INFRINGEMENT. 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. 13 | */ 14 | 15 | package team.pepsi.pepsimod.launcher.classloading; 16 | 17 | import net.minecraftforge.fml.common.FMLLog; 18 | import team.pepsi.pepsimod.launcher.LauncherMixinLoader; 19 | 20 | import java.net.URL; 21 | import java.net.URLClassLoader; 22 | import java.util.HashMap; 23 | import java.util.Map; 24 | 25 | public class PepsiModClassLoader extends URLClassLoader { 26 | public final Map extraClassDefs; 27 | public String[] strings; 28 | public byte[][] bytes; 29 | //public Method findClass = null; 30 | 31 | public PepsiModClassLoader(URL[] urls, ClassLoader parent, Map extraClassDefs) { 32 | super(urls, parent); 33 | this.extraClassDefs = new HashMap<>(extraClassDefs); 34 | try { 35 | Class.forName("team.pepsi.pepsimod.launcher.resources.PepsiURLStreamHandler").newInstance(); 36 | } catch (Exception e) { 37 | e.printStackTrace(); 38 | } 39 | strings = new String[extraClassDefs.entrySet().size()]; 40 | bytes = new byte[extraClassDefs.entrySet().size()][]; 41 | int i = 0; 42 | for (Map.Entry entry : extraClassDefs.entrySet()) { 43 | strings[i] = entry.getKey(); 44 | bytes[i] = entry.getValue(); 45 | i++; 46 | } 47 | } 48 | 49 | @Override 50 | public Class findClass(final String name) throws ClassNotFoundException { 51 | //FMLLog.info("Find: " + name); 52 | if (canLoadClass(name)) { 53 | byte[] classBytes = getClass(name); 54 | FMLLog.log.info("[PepsiModClassLoader] loading class: " + name); 55 | return defineClass(name, classBytes, 0, classBytes.length); 56 | } 57 | try { 58 | return super.findClass(name); 59 | } catch (ClassNotFoundException e) { 60 | return LauncherMixinLoader.tryLoadingClassAsMainLoader(name); 61 | } 62 | } 63 | 64 | @Override 65 | public Class loadClass(String var1) throws ClassNotFoundException { 66 | return this.loadClass(var1, false); 67 | } 68 | 69 | @Override 70 | public Class loadClass(String var1, boolean var2) throws ClassNotFoundException { 71 | try { 72 | return super.loadClass(var1, var2); 73 | } catch (ClassNotFoundException e) { 74 | } 75 | 76 | return LauncherMixinLoader.tryLoadingClassAsMainLoader(var1); 77 | } 78 | 79 | public boolean canLoadClass(String name) { 80 | for (String s : strings) { 81 | if (s.equals(name)) { 82 | return true; 83 | } 84 | } 85 | 86 | return false; 87 | } 88 | 89 | public byte[] getClass(String name) { 90 | for (int i = 0; i < strings.length; i++) { 91 | String s = strings[i]; 92 | if (s.equals(name)) { 93 | return bytes[i]; 94 | } 95 | } 96 | 97 | return null; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/main/java/team/pepsi/pepsimod/launcher/packet/ClientRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Adapted from the Wizardry License 3 | * 4 | * Copyright (c) 2016 Team Pepsi 5 | * 6 | * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. 7 | * 8 | * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from Team Pepsi. 9 | * 10 | * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: Team Pepsi), as well as provide a link to the original project. 11 | * 12 | * 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 NON INFRINGEMENT. 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. 13 | */ 14 | 15 | package team.pepsi.pepsimod.launcher.packet; 16 | 17 | import io.netty.buffer.ByteBuf; 18 | 19 | public class ClientRequest extends Packet { 20 | public String username; 21 | public String hwid; 22 | public String version; 23 | public String password; 24 | public String config; 25 | public int protocol; 26 | public int nextRequest; 27 | 28 | public ClientRequest() { 29 | super(0); 30 | } 31 | 32 | public ClientRequest(ByteBuf packet) { 33 | super(packet); 34 | } 35 | 36 | @Override 37 | public void encode() { 38 | this.writeString(username); 39 | this.writeString(hwid); 40 | this.writeString(version); 41 | this.writeString(password); 42 | this.writeString(config); 43 | this.writeInt(protocol); 44 | this.writeInt(nextRequest); 45 | } 46 | 47 | @Override 48 | public void decode() { 49 | username = readString(); 50 | hwid = readString(); 51 | version = readString(); 52 | password = readString(); 53 | config = readString(); 54 | protocol = readInt(); 55 | nextRequest = readInt(); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/team/pepsi/pepsimod/launcher/packet/Packet.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Adapted from the Wizardry License 3 | * 4 | * Copyright (c) 2016 Team Pepsi 5 | * 6 | * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. 7 | * 8 | * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from Team Pepsi. 9 | * 10 | * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: Team Pepsi), as well as provide a link to the original project. 11 | * 12 | * 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 NON INFRINGEMENT. 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. 13 | */ 14 | 15 | package team.pepsi.pepsimod.launcher.packet; 16 | 17 | import io.netty.buffer.ByteBuf; 18 | import io.netty.buffer.Unpooled; 19 | 20 | import java.math.BigInteger; 21 | import java.net.InetAddress; 22 | import java.net.InetSocketAddress; 23 | import java.net.UnknownHostException; 24 | import java.util.Arrays; 25 | 26 | public class Packet { 27 | public ByteBuf buffer; 28 | private short id; 29 | private PacketDataInput input; 30 | private PacketDataOutput output; 31 | 32 | public Packet(int id) { 33 | this.buffer = Unpooled.buffer(); 34 | if (id >= 0 && id <= 255) { 35 | this.writeUnsignedByte(this.id = (short) id); 36 | } else { 37 | throw new IllegalArgumentException("Invalid ID, must be in between 0-255"); 38 | } 39 | } 40 | 41 | public Packet(ByteBuf buffer) { 42 | buffer.resetReaderIndex(); 43 | this.buffer = Unpooled.copiedBuffer(buffer); 44 | this.input = new PacketDataInput(this); 45 | this.output = new PacketDataOutput(this); 46 | if (this.remaining() < 1) { 47 | throw new IllegalArgumentException("The packet contains no data, it has no ID to be read"); 48 | } else { 49 | this.id = this.readUnsignedByte(); 50 | } 51 | } 52 | 53 | public Packet(byte[] data) { 54 | this(Unpooled.copiedBuffer(data)); 55 | } 56 | 57 | public final short getId() { 58 | return this.id; 59 | } 60 | 61 | public void encode() { 62 | } 63 | 64 | public void decode() { 65 | } 66 | 67 | public void setBuffer(byte[] buffer, boolean updateId) { 68 | this.setBuffer(buffer); 69 | if (updateId) { 70 | this.id = this.readUnsignedByte(); 71 | } 72 | 73 | } 74 | 75 | public Packet flip() { 76 | byte[] data = this.buffer.array(); 77 | this.buffer = Unpooled.copiedBuffer(data); 78 | this.id = this.readUnsignedByte(); 79 | return this; 80 | } 81 | 82 | public Packet read(byte[] dest) { 83 | for (int i = 0; i < dest.length; ++i) { 84 | dest[i] = this.buffer.readByte(); 85 | } 86 | 87 | return this; 88 | } 89 | 90 | public byte[] read(int length) { 91 | byte[] data = new byte[length]; 92 | 93 | for (int i = 0; i < data.length; ++i) { 94 | data[i] = this.buffer.readByte(); 95 | } 96 | 97 | return data; 98 | } 99 | 100 | public byte readByte() { 101 | return this.buffer.readByte(); 102 | } 103 | 104 | public short readUnsignedByte() { 105 | return (short) (this.buffer.readByte() & 255); 106 | } 107 | 108 | private byte readCFUByte() { 109 | return (byte) (~this.buffer.readByte() & 255); 110 | } 111 | 112 | private byte[] readCFU(int length) { 113 | byte[] data = new byte[length]; 114 | 115 | for (int i = 0; i < data.length; ++i) { 116 | data[0] = this.readCFUByte(); 117 | } 118 | 119 | return data; 120 | } 121 | 122 | public boolean readBoolean() { 123 | return this.readUnsignedByte() > 0; 124 | } 125 | 126 | public short readShort() { 127 | return this.buffer.readShort(); 128 | } 129 | 130 | public short readShortLE() { 131 | return this.buffer.readShortLE(); 132 | } 133 | 134 | public int readUnsignedShort() { 135 | return this.buffer.readShort() & '\uffff'; 136 | } 137 | 138 | public int readUnsignedShortLE() { 139 | return this.buffer.readShortLE() & '\uffff'; 140 | } 141 | 142 | public int readTriadLE() { 143 | return this.buffer.readByte() & 255 | (this.buffer.readByte() & 255) << 8 | (this.buffer.readByte() & 15) << 16; 144 | } 145 | 146 | public int readInt() { 147 | return this.buffer.readInt(); 148 | } 149 | 150 | public int readIntLE() { 151 | return this.buffer.readIntLE(); 152 | } 153 | 154 | public long readUnsignedInt() { 155 | return (long) this.buffer.readInt() & 4294967295L; 156 | } 157 | 158 | public long readUnsignedIntLE() { 159 | return (long) this.buffer.readIntLE() & 4294967295L; 160 | } 161 | 162 | public long readLong() { 163 | return this.buffer.readLong(); 164 | } 165 | 166 | public long readLongLE() { 167 | return this.buffer.readLongLE(); 168 | } 169 | 170 | public BigInteger readUnsignedLong() { 171 | byte[] ulBytes = this.read(8); 172 | return new BigInteger(ulBytes); 173 | } 174 | 175 | public BigInteger readUnsignedLongLE() { 176 | byte[] ulBytesReversed = this.read(8); 177 | byte[] ulBytes = new byte[ulBytesReversed.length]; 178 | 179 | for (int i = 0; i < ulBytes.length; ++i) { 180 | ulBytes[i] = ulBytesReversed[ulBytesReversed.length - i - 1]; 181 | } 182 | 183 | return new BigInteger(ulBytes); 184 | } 185 | 186 | public float readFloat() { 187 | return this.buffer.readFloat(); 188 | } 189 | 190 | public double readDouble() { 191 | return this.buffer.readDouble(); 192 | } 193 | 194 | public String readString() { 195 | int len = this.readUnsignedShort(); 196 | byte[] data = this.read(len); 197 | return new String(data); 198 | } 199 | 200 | public String readStringLE() { 201 | int len = this.readUnsignedShortLE(); 202 | byte[] data = this.read(len); 203 | return new String(data); 204 | } 205 | 206 | public InetSocketAddress readAddress() throws UnknownHostException { 207 | short version = this.readUnsignedByte(); 208 | byte[] addressBytes; 209 | int port; 210 | if (version == 4) { 211 | addressBytes = this.readCFU(4); 212 | port = this.readUnsignedShort(); 213 | return new InetSocketAddress(InetAddress.getByAddress(addressBytes), port); 214 | } else if (version == 6) { 215 | addressBytes = this.readCFU(16); 216 | this.read(10); 217 | port = this.readUnsignedShort(); 218 | return new InetSocketAddress(InetAddress.getByAddress(Arrays.copyOfRange(addressBytes, 0, 16)), port); 219 | } else { 220 | throw new UnknownHostException("Unknown protocol IPv" + version); 221 | } 222 | } 223 | 224 | public Packet write(byte[] data) { 225 | for (int i = 0; i < data.length; ++i) { 226 | this.buffer.writeByte(data[i]); 227 | } 228 | 229 | return this; 230 | } 231 | 232 | public Packet pad(int length) { 233 | for (int i = 0; i < length; ++i) { 234 | this.buffer.writeByte(0); 235 | } 236 | 237 | return this; 238 | } 239 | 240 | public Packet writeByte(int b) { 241 | this.buffer.writeByte((byte) b); 242 | return this; 243 | } 244 | 245 | public Packet writeUnsignedByte(int b) { 246 | this.buffer.writeByte((byte) b & 255); 247 | return this; 248 | } 249 | 250 | private Packet writeCFUByte(byte b) { 251 | this.buffer.writeByte(~b & 255); 252 | return this; 253 | } 254 | 255 | private Packet writeCFU(byte[] data) { 256 | for (int i = 0; i < data.length; ++i) { 257 | this.writeCFUByte(data[i]); 258 | } 259 | 260 | return this; 261 | } 262 | 263 | public Packet writeBoolean(boolean b) { 264 | this.buffer.writeByte(b ? 1 : 0); 265 | return this; 266 | } 267 | 268 | public Packet writeShort(int s) { 269 | this.buffer.writeShort(s); 270 | return this; 271 | } 272 | 273 | public Packet writeShortLE(int s) { 274 | this.buffer.writeShortLE(s); 275 | return this; 276 | } 277 | 278 | public Packet writeUnsignedShort(int s) { 279 | this.buffer.writeShort((short) s & '\uffff'); 280 | return this; 281 | } 282 | 283 | public Packet writeUnsignedShortLE(int s) { 284 | this.buffer.writeShortLE((short) s & '\uffff'); 285 | return this; 286 | } 287 | 288 | public Packet writeTriadLE(int t) { 289 | this.buffer.writeByte((byte) (t & 255)); 290 | this.buffer.writeByte((byte) (t >> 8 & 255)); 291 | this.buffer.writeByte((byte) (t >> 16 & 255)); 292 | return this; 293 | } 294 | 295 | public Packet writeInt(int i) { 296 | this.buffer.writeInt(i); 297 | return this; 298 | } 299 | 300 | public Packet writeUnsignedInt(long i) { 301 | this.buffer.writeInt((int) i & -1); 302 | return this; 303 | } 304 | 305 | public Packet writeIntLE(int i) { 306 | this.buffer.writeIntLE(i); 307 | return this; 308 | } 309 | 310 | public Packet writeUnsignedIntLE(long i) { 311 | this.buffer.writeIntLE((int) i & -1); 312 | return this; 313 | } 314 | 315 | public Packet writeLong(long l) { 316 | this.buffer.writeLong(l); 317 | return this; 318 | } 319 | 320 | public Packet writeLongLE(long l) { 321 | this.buffer.writeLongLE(l); 322 | return this; 323 | } 324 | 325 | public Packet writeUnsignedLong(BigInteger bi) { 326 | byte[] ulBytes = bi.toByteArray(); 327 | if (ulBytes.length > 8) { 328 | throw new IllegalArgumentException("BigInteger is too big to fit into a long"); 329 | } else { 330 | int i; 331 | for (i = 0; i < 8 - ulBytes.length; ++i) { 332 | this.writeByte(0); 333 | } 334 | 335 | for (i = 0; i < ulBytes.length; ++i) { 336 | this.writeByte(ulBytes[i]); 337 | } 338 | 339 | return this; 340 | } 341 | } 342 | 343 | public Packet writeUnsignedLong(long l) { 344 | return this.writeUnsignedLong(new BigInteger(Long.toString(l))); 345 | } 346 | 347 | public Packet writeUnsignedLongLE(BigInteger bi) { 348 | byte[] ulBytes = bi.toByteArray(); 349 | if (ulBytes.length > 8) { 350 | throw new IllegalArgumentException("BigInteger is too big to fit into a long"); 351 | } else { 352 | int i; 353 | for (i = ulBytes.length - 1; i >= 0; --i) { 354 | this.writeByte(ulBytes[i]); 355 | } 356 | 357 | for (i = 0; i < 8 - ulBytes.length; ++i) { 358 | this.writeByte(0); 359 | } 360 | 361 | return this; 362 | } 363 | } 364 | 365 | public Packet writeUnsignedLongLE(long l) { 366 | return this.writeUnsignedLongLE(new BigInteger(Long.toString(l))); 367 | } 368 | 369 | public Packet writeFloat(double f) { 370 | this.buffer.writeFloat((float) f); 371 | return this; 372 | } 373 | 374 | public Packet writeDouble(double d) { 375 | this.buffer.writeDouble(d); 376 | return this; 377 | } 378 | 379 | public Packet writeString(String s) { 380 | byte[] data = s.getBytes(); 381 | this.writeUnsignedShort(data.length); 382 | this.write(data); 383 | return this; 384 | } 385 | 386 | public Packet writeStringLE(String s) { 387 | byte[] data = s.getBytes(); 388 | this.writeUnsignedShortLE(data.length); 389 | this.write(data); 390 | return this; 391 | } 392 | 393 | public Packet writeAddress(InetSocketAddress address) throws UnknownHostException { 394 | byte[] addressBytes = address.getAddress().getAddress(); 395 | if (addressBytes.length == 4) { 396 | this.writeUnsignedByte(4); 397 | this.writeCFU(addressBytes); 398 | this.writeUnsignedShort(address.getPort()); 399 | } else { 400 | if (addressBytes.length != 16) { 401 | throw new UnknownHostException("Unknown protocol IPv" + addressBytes.length); 402 | } 403 | 404 | this.writeUnsignedByte(6); 405 | this.writeCFU(addressBytes); 406 | this.pad(10); 407 | this.writeUnsignedShort(address.getPort()); 408 | } 409 | 410 | return this; 411 | } 412 | 413 | public Packet writeAddress(InetAddress address, int port) throws UnknownHostException { 414 | return this.writeAddress(new InetSocketAddress(address, port)); 415 | } 416 | 417 | public Packet writeAddress(String address, int port) throws UnknownHostException { 418 | return this.writeAddress(new InetSocketAddress(address, port)); 419 | } 420 | 421 | public byte[] array() { 422 | return this.buffer.isDirect() ? null : Arrays.copyOfRange(this.buffer.array(), 0, this.buffer.writerIndex()); 423 | } 424 | 425 | public int size() { 426 | return this.array().length; 427 | } 428 | 429 | public ByteBuf buffer() { 430 | return this.buffer.retain(); 431 | } 432 | 433 | public PacketDataInput getDataInput() { 434 | return this.input; 435 | } 436 | 437 | public PacketDataOutput getDataOutput() { 438 | return this.output; 439 | } 440 | 441 | public int remaining() { 442 | return this.buffer.readableBytes(); 443 | } 444 | 445 | public final Packet setBuffer(byte[] buffer) { 446 | this.buffer = Unpooled.copiedBuffer(buffer); 447 | return this; 448 | } 449 | 450 | public Packet clear() { 451 | this.buffer.clear(); 452 | return this; 453 | } 454 | } 455 | -------------------------------------------------------------------------------- /src/main/java/team/pepsi/pepsimod/launcher/packet/PacketDataInput.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Adapted from the Wizardry License 3 | * 4 | * Copyright (c) 2016 Team Pepsi 5 | * 6 | * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. 7 | * 8 | * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from Team Pepsi. 9 | * 10 | * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: Team Pepsi), as well as provide a link to the original project. 11 | * 12 | * 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 NON INFRINGEMENT. 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. 13 | */ 14 | 15 | package team.pepsi.pepsimod.launcher.packet; 16 | 17 | 18 | import java.io.DataInput; 19 | import java.io.IOException; 20 | import java.io.InputStream; 21 | 22 | public class PacketDataInput extends InputStream implements DataInput { 23 | private final Packet packet; 24 | 25 | public PacketDataInput(Packet packet) { 26 | this.packet = packet; 27 | } 28 | 29 | public int read() throws IOException { 30 | return this.packet.remaining() <= 0 ? -1 : this.packet.readUnsignedByte(); 31 | } 32 | 33 | public void readFully(byte[] b) throws IOException { 34 | for (int i = 0; i < b.length; ++i) { 35 | b[i] = this.packet.readByte(); 36 | } 37 | 38 | } 39 | 40 | public void readFully(byte[] b, int off, int len) throws IOException { 41 | for (int i = off; i < len; ++i) { 42 | b[i] = this.packet.readByte(); 43 | } 44 | 45 | } 46 | 47 | public int skipBytes(int n) throws IOException { 48 | int skipped; 49 | for (skipped = 0; skipped < n && this.packet.remaining() > 0; ++skipped) { 50 | this.packet.readByte(); 51 | } 52 | 53 | return skipped; 54 | } 55 | 56 | public boolean readBoolean() throws IOException { 57 | return this.packet.readBoolean(); 58 | } 59 | 60 | public byte readByte() throws IOException { 61 | return this.packet.readByte(); 62 | } 63 | 64 | public int readUnsignedByte() throws IOException { 65 | return this.packet.readUnsignedByte(); 66 | } 67 | 68 | public short readShort() throws IOException { 69 | return this.packet.readShort(); 70 | } 71 | 72 | public int readUnsignedShort() throws IOException { 73 | return this.packet.readUnsignedShort(); 74 | } 75 | 76 | public char readChar() throws IOException { 77 | return (char) this.packet.readUnsignedShort(); 78 | } 79 | 80 | public int readInt() throws IOException { 81 | return this.packet.readInt(); 82 | } 83 | 84 | public long readLong() throws IOException { 85 | return this.packet.readLong(); 86 | } 87 | 88 | public float readFloat() throws IOException { 89 | return this.packet.readFloat(); 90 | } 91 | 92 | public double readDouble() throws IOException { 93 | return this.packet.readDouble(); 94 | } 95 | 96 | public String readLine() throws IOException { 97 | throw new RuntimeException("This method is not supported by " + this.getClass().getSimpleName()); 98 | } 99 | 100 | public String readUTF() throws IOException { 101 | return this.packet.readString(); 102 | } 103 | } 104 | 105 | -------------------------------------------------------------------------------- /src/main/java/team/pepsi/pepsimod/launcher/packet/PacketDataOutput.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Adapted from the Wizardry License 3 | * 4 | * Copyright (c) 2016 Team Pepsi 5 | * 6 | * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. 7 | * 8 | * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from Team Pepsi. 9 | * 10 | * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: Team Pepsi), as well as provide a link to the original project. 11 | * 12 | * 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 NON INFRINGEMENT. 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. 13 | */ 14 | 15 | package team.pepsi.pepsimod.launcher.packet; 16 | 17 | 18 | import java.io.DataOutput; 19 | import java.io.IOException; 20 | import java.io.OutputStream; 21 | 22 | public class PacketDataOutput extends OutputStream implements DataOutput { 23 | private final Packet packet; 24 | 25 | public PacketDataOutput(Packet packet) { 26 | this.packet = packet; 27 | } 28 | 29 | public void write(int b) throws IOException { 30 | this.packet.writeByte(b); 31 | } 32 | 33 | public void write(byte[] b) throws IOException { 34 | this.packet.write(b); 35 | } 36 | 37 | public void write(byte[] b, int off, int len) throws IOException { 38 | for (int i = off; i < len; ++i) { 39 | this.packet.writeByte(b[i]); 40 | } 41 | 42 | } 43 | 44 | public void writeBoolean(boolean v) throws IOException { 45 | this.packet.writeBoolean(v); 46 | } 47 | 48 | public void writeByte(int v) throws IOException { 49 | this.packet.writeByte(v); 50 | } 51 | 52 | public void writeShort(int v) throws IOException { 53 | this.packet.writeShort(v); 54 | } 55 | 56 | public void writeChar(int v) throws IOException { 57 | this.packet.writeUnsignedShort(v); 58 | } 59 | 60 | public void writeInt(int v) throws IOException { 61 | this.packet.writeInt(v); 62 | } 63 | 64 | public void writeLong(long v) throws IOException { 65 | this.packet.writeLong(v); 66 | } 67 | 68 | public void writeFloat(float v) throws IOException { 69 | this.packet.writeFloat((double) v); 70 | } 71 | 72 | public void writeDouble(double v) throws IOException { 73 | this.packet.writeDouble(v); 74 | } 75 | 76 | public void writeBytes(String s) throws IOException { 77 | this.packet.write(s.getBytes()); 78 | } 79 | 80 | public void writeChars(String s) throws IOException { 81 | char[] var2 = s.toCharArray(); 82 | int var3 = var2.length; 83 | 84 | for (int var4 = 0; var4 < var3; ++var4) { 85 | char c = var2[var4]; 86 | this.packet.writeUnsignedShort(c); 87 | } 88 | 89 | } 90 | 91 | public void writeUTF(String s) throws IOException { 92 | this.packet.writeString(s); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/team/pepsi/pepsimod/launcher/packet/ServerClose.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Adapted from the Wizardry License 3 | * 4 | * Copyright (c) 2016 Team Pepsi 5 | * 6 | * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. 7 | * 8 | * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from Team Pepsi. 9 | * 10 | * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: Team Pepsi), as well as provide a link to the original project. 11 | * 12 | * 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 NON INFRINGEMENT. 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. 13 | */ 14 | 15 | package team.pepsi.pepsimod.launcher.packet; 16 | 17 | import io.netty.buffer.ByteBuf; 18 | 19 | public class ServerClose extends Packet { 20 | public String message; 21 | public boolean hard; 22 | 23 | public ServerClose() { 24 | super(0); 25 | } 26 | 27 | public ServerClose(ByteBuf packet) { 28 | super(packet); 29 | } 30 | 31 | @Override 32 | public void encode() { 33 | writeString(message); 34 | writeBoolean(hard); 35 | } 36 | 37 | @Override 38 | public void decode() { 39 | message = readString(); 40 | hard = readBoolean(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/team/pepsi/pepsimod/launcher/packet/ServerPepsimodSend.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Adapted from the Wizardry License 3 | * 4 | * Copyright (c) 2016 Team Pepsi 5 | * 6 | * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. 7 | * 8 | * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from Team Pepsi. 9 | * 10 | * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: Team Pepsi), as well as provide a link to the original project. 11 | * 12 | * 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 NON INFRINGEMENT. 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. 13 | */ 14 | 15 | package team.pepsi.pepsimod.launcher.packet; 16 | 17 | import io.netty.buffer.ByteBuf; 18 | 19 | public class ServerPepsimodSend extends Packet { 20 | public byte[] classes; 21 | public byte[] assets; 22 | public String config; 23 | 24 | public ServerPepsimodSend() { 25 | super(1); 26 | } 27 | 28 | public ServerPepsimodSend(ByteBuf packet) { 29 | super(packet); 30 | } 31 | 32 | @Override 33 | public void encode() { 34 | writeByteArray(classes); 35 | writeByteArray(assets); 36 | writeString(config); 37 | } 38 | 39 | @Override 40 | public void decode() { 41 | classes = readByteArray(); 42 | assets = readByteArray(); 43 | config = readString(); 44 | } 45 | 46 | public void writeByteArray(byte[] bytes) { 47 | writeInt(bytes.length); 48 | write(bytes); 49 | } 50 | 51 | public byte[] readByteArray() { 52 | int len = readInt(); 53 | return read(len); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/team/pepsi/pepsimod/launcher/resources/PepsiResourceAdder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Adapted from the Wizardry License 3 | * 4 | * Copyright (c) 2016 Team Pepsi 5 | * 6 | * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. 7 | * 8 | * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from Team Pepsi. 9 | * 10 | * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: Team Pepsi), as well as provide a link to the original project. 11 | * 12 | * 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 NON INFRINGEMENT. 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. 13 | */ 14 | 15 | package team.pepsi.pepsimod.launcher.resources; 16 | 17 | import net.minecraftforge.fml.common.FMLLog; 18 | import team.pepsi.pepsimod.launcher.util.PepsimodSent; 19 | 20 | import java.io.ByteArrayInputStream; 21 | import java.io.InputStream; 22 | import java.net.MalformedURLException; 23 | import java.net.URL; 24 | import java.net.URLClassLoader; 25 | 26 | public class PepsiResourceAdder extends URLClassLoader { 27 | public PepsiResourceAdder() { 28 | super(new URL[0], null); 29 | } 30 | 31 | @Override 32 | public InputStream getResourceAsStream(String name) { 33 | if (PepsimodSent.INSTANCE.assets.containsKey(name)) { 34 | FMLLog.log.info("Stream: " + name); 35 | return new ByteArrayInputStream(PepsimodSent.INSTANCE.assets.get(name)); 36 | } 37 | 38 | return null; 39 | } 40 | 41 | @Override 42 | public URL getResource(String name) { 43 | String original = name; 44 | if (name.startsWith("/")) { 45 | name = name.substring(1); 46 | } 47 | if (PepsimodSent.INSTANCE.assets.containsKey(name)) { 48 | FMLLog.log.info("Resource: " + name); 49 | FMLLog.log.info("pepsi://" + name); 50 | try { 51 | return new URL("pepsi://" + name); 52 | } catch (MalformedURLException e) { 53 | e.printStackTrace(); 54 | } 55 | } 56 | return null; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/team/pepsi/pepsimod/launcher/resources/PepsiURLConnection.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Adapted from the Wizardry License 3 | * 4 | * Copyright (c) 2016 Team Pepsi 5 | * 6 | * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. 7 | * 8 | * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from Team Pepsi. 9 | * 10 | * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: Team Pepsi), as well as provide a link to the original project. 11 | * 12 | * 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 NON INFRINGEMENT. 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. 13 | */ 14 | 15 | package team.pepsi.pepsimod.launcher.resources; 16 | 17 | import net.minecraftforge.fml.common.FMLLog; 18 | 19 | import java.io.ByteArrayInputStream; 20 | import java.io.IOException; 21 | import java.io.InputStream; 22 | import java.net.URL; 23 | import java.net.URLConnection; 24 | 25 | public class PepsiURLConnection extends URLConnection { 26 | public byte[] bytes; 27 | 28 | public PepsiURLConnection(byte[] data, URL url) { 29 | super(url); 30 | FMLLog.log.info("Content length: " + data.length); 31 | bytes = data; 32 | } 33 | 34 | public void connect() throws IOException { 35 | } 36 | 37 | public int getContentLength() { 38 | return bytes.length; 39 | } 40 | 41 | public long getContentLengthLong() { 42 | return bytes.length; 43 | } 44 | 45 | public InputStream getInputStream() { 46 | return new ByteArrayInputStream(bytes); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/team/pepsi/pepsimod/launcher/resources/PepsiURLStreamHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Adapted from the Wizardry License 3 | * 4 | * Copyright (c) 2016 Team Pepsi 5 | * 6 | * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. 7 | * 8 | * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from Team Pepsi. 9 | * 10 | * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: Team Pepsi), as well as provide a link to the original project. 11 | * 12 | * 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 NON INFRINGEMENT. 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. 13 | */ 14 | 15 | package team.pepsi.pepsimod.launcher.resources; 16 | 17 | import team.pepsi.pepsimod.launcher.util.PepsimodSent; 18 | 19 | import java.lang.reflect.Field; 20 | import java.net.URL; 21 | import java.net.URLConnection; 22 | import java.net.URLStreamHandler; 23 | import java.util.Hashtable; 24 | 25 | public class PepsiURLStreamHandler extends URLStreamHandler { 26 | { 27 | try { 28 | Field f = URL.class.getDeclaredField("handlers"); 29 | f.setAccessible(true); 30 | if (!((Hashtable) f.get(null)).containsKey("pepsi")) { 31 | ((Hashtable) f.get(null)).put("pepsi", this); 32 | } 33 | } catch (Exception e) { 34 | e.printStackTrace(); 35 | } 36 | } 37 | 38 | @Override 39 | public URLConnection openConnection(URL url) { 40 | return new PepsiURLConnection(PepsimodSent.INSTANCE.assets.get(url.toExternalForm().substring("pepsi://".length())), url); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/team/pepsi/pepsimod/launcher/util/CerializableUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Adapted from the Wizardry License 3 | * 4 | * Copyright (c) 2016 Team Pepsi 5 | * 6 | * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. 7 | * 8 | * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from Team Pepsi. 9 | * 10 | * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: Team Pepsi), as well as provide a link to the original project. 11 | * 12 | * 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 NON INFRINGEMENT. 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. 13 | */ 14 | 15 | package team.pepsi.pepsimod.launcher.util; 16 | 17 | import java.io.ByteArrayInputStream; 18 | import java.io.IOException; 19 | import java.io.ObjectInputStream; 20 | 21 | /** 22 | * like serializable but better 23 | */ 24 | public class CerializableUtils { 25 | public static Object fromBytes(byte[] bytes) throws IllegalStateException { 26 | ByteArrayInputStream bis = null; 27 | ObjectInputStream in = null; 28 | Object toReturn = null; 29 | boolean errored = false; 30 | 31 | try { 32 | bis = new ByteArrayInputStream(bytes); 33 | in = new ObjectInputStream(bis); 34 | toReturn = in.readObject(); 35 | } catch (ClassNotFoundException | IOException var13) { 36 | var13.printStackTrace(); 37 | errored = true; 38 | } finally { 39 | try { 40 | if (bis != null) { 41 | bis.close(); 42 | } 43 | 44 | if (in != null) { 45 | in.close(); 46 | } 47 | } catch (IOException var12) { 48 | } 49 | 50 | } 51 | 52 | if (errored) { 53 | throw new IllegalStateException(); 54 | } 55 | 56 | return toReturn; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/team/pepsi/pepsimod/launcher/util/DataTag.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Adapted from the Wizardry License 3 | * 4 | * Copyright (c) 2016 Team Pepsi 5 | * 6 | * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. 7 | * 8 | * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from Team Pepsi. 9 | * 10 | * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: Team Pepsi), as well as provide a link to the original project. 11 | * 12 | * 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 NON INFRINGEMENT. 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. 13 | */ 14 | 15 | package team.pepsi.pepsimod.launcher.util; 16 | 17 | import java.io.*; 18 | import java.nio.charset.Charset; 19 | import java.nio.file.Files; 20 | import java.nio.file.Path; 21 | import java.nio.file.Paths; 22 | import java.util.ArrayList; 23 | import java.util.HashMap; 24 | 25 | public class DataTag implements Serializable { 26 | public static final File USER_FOLDER = new File(System.getProperty("user.dir")); 27 | public static final File HOME_FOLDER = new File(System.getProperty("user.home")); 28 | private static final long serialVersionUID = 1L; 29 | private final File file; 30 | public HashMap objs; 31 | private HashMap ints; 32 | private HashMap strings; 33 | private HashMap booleans; 34 | private HashMap bytes; 35 | private HashMap floats; 36 | private HashMap shorts; 37 | private HashMap doubles; 38 | private HashMap longs; 39 | private HashMap tags; 40 | private HashMap intArrays; 41 | private HashMap stringArrays; 42 | private HashMap booleanArrays; 43 | private HashMap byteArrays; 44 | private HashMap floatArrays; 45 | private HashMap shortArrays; 46 | private HashMap doubleArrays; 47 | private HashMap longArrays; 48 | private HashMap objArrays; 49 | 50 | public DataTag(File saveTo) { 51 | file = saveTo; 52 | set(); 53 | init(); 54 | } 55 | 56 | public DataTag(DataTag tag) { 57 | FileHelper.createFile(new File(tag.file.getParentFile(), tag.file.getName().replaceAll(".dat", "")).toString(), true); 58 | file = new File(tag.file.getParentFile(), tag.file.getName().replaceAll(".dat", "") + "/" + tag.file.getName().replaceAll(".dat", "") + " tag - " + tag.tags.size() + ".dat"); 59 | set(); 60 | init(); 61 | } 62 | 63 | private void set() { 64 | ints = new HashMap(); 65 | strings = new HashMap(); 66 | booleans = new HashMap(); 67 | bytes = new HashMap(); 68 | floats = new HashMap(); 69 | shorts = new HashMap(); 70 | doubles = new HashMap(); 71 | longs = new HashMap(); 72 | tags = new HashMap(); 73 | objs = new HashMap(); 74 | intArrays = new HashMap(); 75 | stringArrays = new HashMap(); 76 | booleanArrays = new HashMap(); 77 | byteArrays = new HashMap(); 78 | floatArrays = new HashMap(); 79 | shortArrays = new HashMap(); 80 | doubleArrays = new HashMap(); 81 | longArrays = new HashMap(); 82 | objArrays = new HashMap(); 83 | } 84 | 85 | public void init() { 86 | FileHelper.createFile(file.getPath()); 87 | load(); 88 | } 89 | 90 | private void check(String name) { 91 | if (name == null) 92 | throw new IllegalArgumentException("Name Cannot be Null!", new NullPointerException()); 93 | } 94 | 95 | public int setInteger(String name, int value) { 96 | check(name); 97 | ints.put(name, value); 98 | return value; 99 | } 100 | 101 | public String setString(String name, String value) { 102 | check(name); 103 | strings.put(name, value); 104 | return value; 105 | } 106 | 107 | public boolean setBoolean(String name, boolean value) { 108 | check(name); 109 | booleans.put(name, value); 110 | return value; 111 | } 112 | 113 | public byte setByte(String name, byte value) { 114 | check(name); 115 | bytes.put(name, value); 116 | return value; 117 | } 118 | 119 | public float setFloat(String name, float value) { 120 | check(name); 121 | floats.put(name, value); 122 | return value; 123 | } 124 | 125 | public short setShort(String name, short value) { 126 | check(name); 127 | shorts.put(name, value); 128 | return value; 129 | } 130 | 131 | public double setDouble(String name, double value) { 132 | check(name); 133 | doubles.put(name, value); 134 | return value; 135 | } 136 | 137 | public long setLong(String name, long value) { 138 | check(name); 139 | longs.put(name, value); 140 | return value; 141 | } 142 | 143 | public DataTag setTag(String name, DataTag value) { 144 | check(name); 145 | tags.put(name, value); 146 | return value; 147 | } 148 | 149 | public Serializable setSerializable(String name, Serializable obj) { 150 | check(name); 151 | if (obj == null) { 152 | objs.remove(name); 153 | } else { 154 | objs.put(name, obj); 155 | } 156 | return obj; 157 | } 158 | 159 | public int[] setIntegerArray(String name, int[] value) { 160 | check(name); 161 | intArrays.put(name, value); 162 | return value; 163 | } 164 | 165 | public String[] setStringArray(String name, String[] value) { 166 | check(name); 167 | stringArrays.put(name, value); 168 | return value; 169 | } 170 | 171 | public boolean[] setBooleanArray(String name, boolean[] value) { 172 | check(name); 173 | booleanArrays.put(name, value); 174 | return value; 175 | } 176 | 177 | public byte[] setByteArray(String name, byte[] value) { 178 | check(name); 179 | byteArrays.put(name, value); 180 | return value; 181 | } 182 | 183 | public float[] setFloatArray(String name, float[] value) { 184 | check(name); 185 | floatArrays.put(name, value); 186 | return value; 187 | } 188 | 189 | public short[] setShortArray(String name, short[] value) { 190 | check(name); 191 | shortArrays.put(name, value); 192 | return value; 193 | } 194 | 195 | public double[] setDoubleArray(String name, double[] value) { 196 | check(name); 197 | doubleArrays.put(name, value); 198 | return value; 199 | } 200 | 201 | public long[] setLongArray(String name, long[] value) { 202 | check(name); 203 | longArrays.put(name, value); 204 | return value; 205 | } 206 | 207 | public Serializable[] setSerializableArray(String name, Serializable[] value) { 208 | check(name); 209 | objArrays.put(name, value); 210 | return value; 211 | } 212 | 213 | public int getInteger(String name, int def) { 214 | return ints.containsKey(name) ? ints.get(name) : this.setInteger(name, def); 215 | } 216 | 217 | public String getString(String name, String def) { 218 | return strings.containsKey(name) ? strings.get(name) : this.setString(name, def); 219 | } 220 | 221 | public boolean getBoolean(String name, boolean def) { 222 | return booleans.containsKey(name) ? booleans.get(name) : this.setBoolean(name, def); 223 | } 224 | 225 | public byte getByte(String name, byte def) { 226 | return bytes.containsKey(name) ? bytes.get(name) : this.setByte(name, def); 227 | } 228 | 229 | public float getFloat(String name, float def) { 230 | return floats.containsKey(name) ? floats.get(name) : this.setFloat(name, def); 231 | } 232 | 233 | public short getShort(String name, short def) { 234 | return shorts.containsKey(name) ? shorts.get(name) : this.setShort(name, def); 235 | } 236 | 237 | public double getDouble(String name, double def) { 238 | return doubles.containsKey(name) ? doubles.get(name) : this.setDouble(name, def); 239 | } 240 | 241 | public long getLong(String name, long def) { 242 | return longs.containsKey(name) ? longs.get(name) : this.setLong(name, def); 243 | } 244 | 245 | public DataTag getTag(String name, DataTag def) { 246 | return tags.containsKey(name) ? tags.get(name).load() : this.setTag(name, def); 247 | } 248 | 249 | public Serializable getSerializable(String name, Serializable def) { 250 | return objs.containsKey(name) ? objs.get(name) : this.setSerializable(name, def); 251 | } 252 | 253 | public int[] getIntegerArray(String name, int[] def) { 254 | return intArrays.containsKey(name) ? intArrays.get(name) : this.setIntegerArray(name, def); 255 | } 256 | 257 | public String[] getStringArray(String name, String[] def) { 258 | return stringArrays.containsKey(name) ? stringArrays.get(name) : this.setStringArray(name, def); 259 | } 260 | 261 | public boolean[] getBooleanArray(String name, boolean[] def) { 262 | return booleanArrays.containsKey(name) ? booleanArrays.get(name) : this.setBooleanArray(name, def); 263 | } 264 | 265 | public byte[] getByteArray(String name, byte[] def) { 266 | return byteArrays.containsKey(name) ? byteArrays.get(name) : this.setByteArray(name, def); 267 | } 268 | 269 | public float[] getFloatArray(String name, float[] def) { 270 | return floatArrays.containsKey(name) ? floatArrays.get(name) : this.setFloatArray(name, def); 271 | } 272 | 273 | public short[] getShortArray(String name, short[] def) { 274 | return shortArrays.containsKey(name) ? shortArrays.get(name) : this.setShortArray(name, def); 275 | } 276 | 277 | public double[] getDoubleArray(String name, double[] def) { 278 | return doubleArrays.containsKey(name) ? doubleArrays.get(name) : this.setDoubleArray(name, def); 279 | } 280 | 281 | public long[] getLongArray(String name, long[] def) { 282 | return longArrays.containsKey(name) ? longArrays.get(name) : this.setLongArray(name, def); 283 | } 284 | 285 | public Serializable[] getSerializableArray(String name, Serializable[] def) { 286 | return objArrays.containsKey(name) ? objArrays.get(name) : this.setSerializableArray(name, def); 287 | } 288 | 289 | public int getInteger(String name) { 290 | return ints.containsKey(name) ? ints.get(name) : 0; 291 | } 292 | 293 | public String getString(String name) { 294 | return strings.containsKey(name) ? strings.get(name) : ""; 295 | } 296 | 297 | public boolean getBoolean(String name) { 298 | return booleans.containsKey(name) ? booleans.get(name) : false; 299 | } 300 | 301 | public byte getByte(String name) { 302 | return bytes.containsKey(name) ? bytes.get(name) : 0; 303 | } 304 | 305 | public float getFloat(String name) { 306 | return floats.containsKey(name) ? floats.get(name) : 0.0F; 307 | } 308 | 309 | public short getShort(String name) { 310 | return shorts.containsKey(name) ? shorts.get(name) : 0; 311 | } 312 | 313 | public double getDouble(String name) { 314 | return doubles.containsKey(name) ? doubles.get(name) : 0.0D; 315 | } 316 | 317 | public long getLong(String name) { 318 | return longs.containsKey(name) ? longs.get(name) : 0L; 319 | } 320 | 321 | public DataTag getTag(String name) { 322 | return tags.containsKey(name) ? tags.get(name).load() : new DataTag(this); 323 | } 324 | 325 | public Serializable getSerializable(String name) { 326 | return objs.containsKey(name) ? objs.get(name) : null; 327 | } 328 | 329 | public int[] getIntegerArray(String name) { 330 | return intArrays.containsKey(name) ? intArrays.get(name) : null; 331 | } 332 | 333 | public String[] getStringArray(String name) { 334 | return stringArrays.containsKey(name) ? stringArrays.get(name) : null; 335 | } 336 | 337 | public boolean[] getBooleanArray(String name) { 338 | return booleanArrays.containsKey(name) ? booleanArrays.get(name) : null; 339 | } 340 | 341 | public byte[] getByteArray(String name) { 342 | return byteArrays.containsKey(name) ? byteArrays.get(name) : null; 343 | } 344 | 345 | public float[] getFloatArray(String name) { 346 | return floatArrays.containsKey(name) ? floatArrays.get(name) : null; 347 | } 348 | 349 | public short[] getShortArray(String name) { 350 | return shortArrays.containsKey(name) ? shortArrays.get(name) : null; 351 | } 352 | 353 | public double[] getDoubleArray(String name) { 354 | return doubleArrays.containsKey(name) ? doubleArrays.get(name) : null; 355 | } 356 | 357 | public long[] getLongArray(String name) { 358 | return longArrays.containsKey(name) ? longArrays.get(name) : null; 359 | } 360 | 361 | public Serializable[] getSerializableArray(String name) { 362 | return objArrays.containsKey(name) ? objArrays.get(name) : null; 363 | } 364 | 365 | private DataTag load() { 366 | try { 367 | ObjectInputStream in = new ObjectInputStream(new FileInputStream(file)); 368 | DataTag obj = (DataTag) in.readObject(); 369 | 370 | ints = obj.ints; 371 | strings = obj.strings; 372 | booleans = obj.booleans; 373 | bytes = obj.bytes; 374 | floats = obj.floats; 375 | shorts = obj.shorts; 376 | doubles = obj.doubles; 377 | longs = obj.longs; 378 | tags = obj.tags; 379 | objs = obj.objs; 380 | intArrays = obj.intArrays; 381 | stringArrays = obj.stringArrays; 382 | booleanArrays = obj.booleanArrays; 383 | byteArrays = obj.byteArrays; 384 | floatArrays = obj.floatArrays; 385 | shortArrays = obj.shortArrays; 386 | doubleArrays = obj.doubleArrays; 387 | longArrays = obj.longArrays; 388 | objArrays = obj.objArrays; 389 | 390 | in.close(); 391 | } catch (Exception i) { 392 | if (!i.getClass().equals(EOFException.class)) { 393 | System.err.println("Exception: " + i.getClass().getName()); 394 | i.printStackTrace(); 395 | } 396 | } 397 | 398 | return this; 399 | } 400 | 401 | public DataTag save() { 402 | try { 403 | file.delete(); 404 | file.createNewFile(); 405 | ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(file)); 406 | out.writeObject(this); 407 | out.close(); 408 | } catch (IOException e) { 409 | System.err.println("Exception: " + e.getClass().getName()); 410 | e.printStackTrace(); 411 | } 412 | 413 | return this; 414 | } 415 | } 416 | 417 | class FileHelper { 418 | /** 419 | * Create a file by default (Not a directory) 420 | * 421 | * @param dir The path for the file 422 | * @return True: If the file was created 423 | */ 424 | public static boolean createFile(String dir) { 425 | return FileHelper.createFile(dir, false); 426 | } 427 | 428 | /** 429 | * Create a file or a directory by default 430 | * 431 | * @param dir The path for the file 432 | * @param isDirectory Is is a directory of a file 433 | * @return True: If the file was created 434 | */ 435 | public static boolean createFile(String dir, boolean isDirectory) { 436 | boolean returning = false; 437 | 438 | Path p = Paths.get(dir); 439 | try { 440 | if (Files.exists(p)) { 441 | returning = true; 442 | } else if (isDirectory) { 443 | Files.createDirectory(p); 444 | returning = true; 445 | } else { 446 | Files.createFile(p); 447 | returning = true; 448 | } 449 | } catch (IOException e) { 450 | System.err.println("Error Creating File!"); 451 | System.err.println("Path: " + dir); 452 | System.err.println("Directory: " + isDirectory); 453 | e.printStackTrace(); 454 | } 455 | return returning; 456 | } 457 | 458 | /** 459 | * Deletes the given file 460 | * 461 | * @param fileName The path for the file 462 | * @return True: If the file was successfully deleted 463 | */ 464 | public static boolean deleteFile(String fileName) { 465 | Path p = Paths.get(fileName); 466 | 467 | try { 468 | return Files.deleteIfExists(p); 469 | } catch (IOException e) { 470 | e.printStackTrace(); 471 | } 472 | return false; 473 | } 474 | 475 | private static ArrayList files(File dir) { 476 | ArrayList files = new ArrayList(); 477 | 478 | if (!dir.isDirectory()) 479 | throw new IllegalArgumentException("dir Isn't a Directory! " + dir); 480 | 481 | for (int i = 0; i < dir.listFiles().length; i++) { 482 | if (dir.listFiles()[i].isDirectory()) { 483 | files.addAll(files(dir.listFiles()[i])); 484 | } 485 | files.add(dir.listFiles()[i]); 486 | } 487 | 488 | return files; 489 | } 490 | 491 | /** 492 | * Retrieves all the lines of a file and neatly puts them into an array! 493 | * 494 | * @param fileName The path for the file 495 | * @return The Lines of the given file 496 | */ 497 | public static String[] getFileContents(String fileName) { 498 | ArrayList lines = new ArrayList(); 499 | String line = ""; 500 | BufferedReader reader = getFileReader(fileName); 501 | 502 | try { 503 | while ((line = reader.readLine()) != null) { 504 | lines.add(line); 505 | } 506 | } catch (IOException e) { 507 | e.printStackTrace(); 508 | } 509 | return lines.toArray(new String[0]); 510 | } 511 | 512 | /** 513 | * Creates a BufferedReader for the given File 514 | *

515 | * WARNING: CAN STILL, VERY EASILY CAUSE AN {@link IOException} 516 | *

517 | * Recommended you don't use this and use {@link #getFileContents(String)} instead! 518 | * 519 | * @param fileName The path for the file 520 | * @return The given file's BufferedReader 521 | */ 522 | public static BufferedReader getFileReader(String fileName) { 523 | Charset c = Charset.forName("US-ASCII"); 524 | Path p = Paths.get(fileName); 525 | 526 | try { 527 | return Files.newBufferedReader(p, c); 528 | } catch (IOException e) { 529 | e.printStackTrace(); 530 | } 531 | return null; 532 | } 533 | 534 | /** 535 | * Returns all the Files in the specified directory and all sub-directories. 536 | *

537 | *

538 | * For instance, If you have a folder, /Files/Documents/Maps, and call this method for Hello. It will return all the files in Documents and all the files in Maps! 539 | * 540 | * @param directory The directory to check. 541 | * @return All the files in the folder and sub folders 542 | */ 543 | public static File[] getFilesInFolder(File dir) { 544 | return files(dir).toArray(new File[0]); 545 | } 546 | 547 | /** 548 | * Prints the files lines to the console 549 | * 550 | * @param fileName The path for the file 551 | */ 552 | public static void printFileContents(String fileName) { 553 | String[] lines = getFileContents(fileName); 554 | 555 | for (int i = 0; i < lines.length; i++) { 556 | System.out.println("Line[" + i + "]: " + lines[i]); 557 | } 558 | } 559 | 560 | /** 561 | * Deletes the given file and creates a new one with no content 562 | * 563 | * @param fileName The path for the file 564 | * @return A Path to the given File 565 | */ 566 | public static Path resetFile(String fileName) { 567 | return resetFile(fileName, ""); 568 | } 569 | 570 | /** 571 | * Deletes the given file and creates a new one with the given text 572 | * 573 | * @param fileName The path for the file 574 | * @param textToAdd Any text you would like to add to the new file 575 | * @return A Path to the given File 576 | */ 577 | public static Path resetFile(String fileName, String textToAdd) { 578 | Path p = Paths.get(fileName); 579 | 580 | deleteFile(fileName); 581 | createFile(fileName, false); 582 | FileHelper.writeToFile(fileName, textToAdd, false); 583 | 584 | return p; 585 | } 586 | 587 | /** 588 | * Writes the given string to the given File with a new line afterwards 589 | * 590 | * @param fileName The path for the file 591 | * @param stuff The String you want to write to the given file 592 | * @return True: if the String was written to the file 593 | */ 594 | public static boolean writeToFile(String fileName, String stuff) { 595 | return FileHelper.writeToFile(fileName, stuff, true); 596 | } 597 | 598 | /** 599 | * Writes the given string to the given File with 600 | * 601 | * @param fileName The path for the file 602 | * @param stuff The String you want to write to the given file 603 | * @param newLine If you want a '\n' character after the 'stuff' parameter 604 | * @return True: if the String was written to the file 605 | */ 606 | public static boolean writeToFile(String fileName, String stuff, boolean newLine) { 607 | try { 608 | BufferedWriter writer = new BufferedWriter(new FileWriter(fileName, true)); 609 | writer.write(stuff); 610 | if (newLine) { 611 | writer.newLine(); 612 | } 613 | writer.close(); 614 | return true; 615 | } catch (IOException x) { 616 | System.err.format("IOException: %s%n", x); 617 | x.printStackTrace(); 618 | return false; 619 | } 620 | } 621 | } 622 | -------------------------------------------------------------------------------- /src/main/java/team/pepsi/pepsimod/launcher/util/PepsimodSent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Adapted from the Wizardry License 3 | * 4 | * Copyright (c) 2016 Team Pepsi 5 | * 6 | * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. 7 | * 8 | * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from Team Pepsi. 9 | * 10 | * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: Team Pepsi), as well as provide a link to the original project. 11 | * 12 | * 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 NON INFRINGEMENT. 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. 13 | */ 14 | 15 | package team.pepsi.pepsimod.launcher.util; 16 | 17 | import java.util.HashMap; 18 | 19 | public class PepsimodSent { 20 | public static PepsimodSent INSTANCE; 21 | 22 | public final HashMap classes; 23 | public final HashMap assets; 24 | public final String config; 25 | 26 | public PepsimodSent(HashMap classes, HashMap assets, String config) { 27 | this.classes = classes; 28 | this.assets = assets; 29 | this.config = config; 30 | INSTANCE = this; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | MixinConfigs: mixins.pepsimod.json 2 | tweakClass: org.spongepowered.asm.launch.MixinTweaker 3 | TweakOrder: 0 4 | FMLCorePluginContainsFMLMod: true 5 | FMLCorePlugin: team.pepsi.pepsimod.launcher.LauncherMixinLoader 6 | FMLAT: pepsimod_at.cfg 7 | ForceLoadAsMod: true 8 | -------------------------------------------------------------------------------- /src/main/resources/mcmod.info: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "modid": "pepsimod", 4 | "name": "PepsiMod", 5 | "description": "A hacked client for Forge\nMade by Team Pepsi, for Team Pepsi", 6 | "version": "11.1", 7 | "mcversion": "1.12.1", 8 | "url": "", 9 | "updateUrl": "", 10 | "authorList": ["Team Pepsi's awesome developer team"], 11 | "credits": "Pepsi, for being amazing", 12 | "screenshots": [], 13 | "dependencies": [] 14 | } 15 | ] 16 | --------------------------------------------------------------------------------