MinecraftTabPatcher/Program.cs
/// <summary>
/// Patches the given minecraft version and returns the new patched version.
/// The patcher will create a new version directory and create a new jar file.
/// The jar file is based on the original <paramref name="version"/>.
/// The patcher will copy any assets from the orignal jar file.
/// The content of the META-INF directory will not be copied.
/// All classes will be analysed and scanned for a keyPressed method.
/// The patcher will replace 0x110102 from the keyPressed methods.
/// 0x11 (sipush) is the java bytecode instruction that loads the next two
/// bytes as short value onto the stack. Where 0x0102 is the short value for
/// 258 which is the minecraft keycode for tab. 0x0102 will be replaced with
/// 0xFFFF which is an invalid keycode. 
/// </summary>
/// <param name="version"></param>
/// <param name="postfix"></param>
/// <returns></returns>
Patches the given minecraft version and returns the new patched version.
The patcher will create a new version directory and create a new jar file.
The jar file is based on the original .
The patcher will copy any assets from the orignal jar file.
The content of the META-INF directory will not be copied.
All classes will be analysed and scanned for a keyPressed method.
The patcher will replace 0x110102 from the keyPressed methods.
0x11 (sipush) is the java bytecode instruction that loads the next two
bytes as short value onto the stack. Where 0x0102 is the short value for
258 which is the minecraft keycode for tab. 0x0102 will be replaced with
0xFFFF which is an invalid keycode.
Patches the given minecraft version and returns the new patched version . The patcher will create a new version directory and create a new jar file . The jar file is based on the original . The patcher will copy any assets from the orignal jar file . The content of the META - INF directory will not be copied . All classes will be analysed and scanned for a keyPressed method . The patcher will replace 0x110102 from the keyPressed methods . 0x11 ( sipush ) is the java bytecode instruction that loads the next two bytes as short value onto the stack . Where 0x0102 is the short value for 258 which is the minecraft keycode for tab . 0x0102 will be replaced with 0xFFFF which is an invalid keycode .
private static MinecraftVersion Patch(MinecraftVersion version, string postfix)
        {
            Console.WriteLine("Start pathching '{0}'...", version.ID);
            Console.WriteLine("------------------------------------------------------");
            var parentPath = Path.GetDirectoryName(version.Path);
            var template = version.ID + "-" + postfix;
            var id = template;
            var path = Path.Combine(parentPath, id);
            var counter = 1;
            while (Directory.Exists(path))
            {
                counter++;
                id = template + counter;
                path = Path.Combine(parentPath, id);
            }
            Console.WriteLine("Creating patched version '{0}'...", id);
            var patchedVersion = new MinecraftVersion(path);
            var buffer = new byte[1024 * 8];
            using (var javaFile = version.OpenJavaFile())
            {
                using (var output = new FileStream(patchedVersion.PathJar, FileMode.Create))
                {
                    using (var outputZip = new ZipOutputStream(output))
                    {
                        outputZip.UseZip64 = UseZip64.Off;
                        var files = javaFile.Zip.Count;
                        for (int i = 0; i < files; i++)
                        {
                            var entry = javaFile.Zip[i];
                            if (entry.Name.Contains("META-INF/"))
                            {
                                continue;
                            }
                            var outputEntry = new ZipEntry(entry.Name);
                            outputEntry.DateTime = entry.DateTime;
                            outputEntry.Size = entry.Size;
                            outputZip.PutNextEntry(outputEntry);
                            if (Path.GetExtension(entry.Name) == ".class")
                            {
                                var javaClass = javaFile.GetClass(entry);
                                var javaClassInfo = javaClass.GetConstant<JavaConstantClassInfo>(javaClass.ThisClass);
                                var javaClassName = javaClass.GetConstantUtf8(javaClassInfo.NameIndex);
                                var javaMethod = javaClass.GetMethod("keyPressed");
                                if (javaMethod != null)
                                {
                                     info
                                    var javaMethodName = javaClass.GetConstantUtf8(javaMethod.NameIndex);
                                    var javaMethodDescriptor = javaClass.GetConstantUtf8(javaMethod.DescriptorIndex);
                                    var javaCodeAttribute = javaMethod.GetCodeAttribute();
                                    if (javaCodeAttribute != null)
                                    {
                                        var code = javaCodeAttribute.Code;
                                        var index = 0;
                                        while ((index = Utils.BinaryIndexOf(code, OrginalCode, index)) >= 0)
                                        {
                                            Console.WriteLine("Patching bytecode from '{0}.{1}{2}' at position {3}...", javaClassName, javaMethodName, javaMethodDescriptor, index);
                                            code[index + 1] = 0xFF;
                                            code[index + 2] = 0xFF;
                                            index++;
                                        }
                                    }
                                }
                                javaClass.Write(outputZip);
                            }
                            else
                            {
                                using (var inputStream = javaFile.GetFileStream(entry))
                                {
                                    StreamUtils.Copy(inputStream, outputZip, buffer);
                                }
                            }
                        }
                    }
                }
            }
            Console.WriteLine("Creating json file...");
            var patchedInfo = new MinecraftVersionInfo()
            {
                ID = id,
                InheritsFrom = version.ID,
                Type = "custom",
                MainClass = "net.minecraft.client.main.Main",
                MinimumLauncherVersion = 21,
            };
            patchedVersion.WriteJsonFile(patchedInfo);
            Console.WriteLine("Version got patched!");
            return patchedVersion;
        }
private static MinecraftVersion Patch ( MinecraftVersion version , string postfix ) { Console . WriteLine ( " " , version . ID ) ; Console . WriteLine ( " " ) ; var parentPath = Path . GetDirectoryName ( version . Path ) ; var template = version . ID + " " + postfix ; var id = template ; var path = Path . Combine ( parentPath , id ) ; var counter = 1 ; while ( Directory . Exists ( path ) ) { counter ++ ; id = template + counter ; path = Path . Combine ( parentPath , id ) ; } Console . WriteLine ( " " , id ) ; var patchedVersion = new MinecraftVersion ( path ) ; var buffer = new byte [ 1024 * 8 ] ; using ( var javaFile = version . OpenJavaFile ( ) ) { using ( var output = new FileStream ( patchedVersion . PathJar , FileMode . Create ) ) { using ( var outputZip = new ZipOutputStream ( output ) ) { outputZip . UseZip64 = UseZip64 . Off ; var files = javaFile . Zip . Count ; for ( int i = 0 ; i < files ; i ++ ) { var entry = javaFile . Zip [ i ] ; if ( entry . Name . Contains ( " " ) ) { continue ; } var outputEntry = new ZipEntry ( entry . Name ) ; outputEntry . DateTime = entry . DateTime ; outputEntry . Size = entry . Size ; outputZip . PutNextEntry ( outputEntry ) ; if ( Path . GetExtension ( entry . Name ) == " " ) { var javaClass = javaFile . GetClass ( entry ) ; var javaClassInfo = javaClass . GetConstant < JavaConstantClassInfo > ( javaClass . ThisClass ) ; var javaClassName = javaClass . GetConstantUtf8 ( javaClassInfo . NameIndex ) ; var javaMethod = javaClass . GetMethod ( " " ) ; if ( javaMethod != null ) { var javaMethodName = javaClass . GetConstantUtf8 ( javaMethod . NameIndex ) ; var javaMethodDescriptor = javaClass . GetConstantUtf8 ( javaMethod . DescriptorIndex ) ; var javaCodeAttribute = javaMethod . GetCodeAttribute ( ) ; if ( javaCodeAttribute != null ) { var code = javaCodeAttribute . Code ; var index = 0 ; while ( ( index = Utils . BinaryIndexOf ( code , OrginalCode , index ) ) >= 0 ) { Console . WriteLine ( " " , javaClassName , javaMethodName , javaMethodDescriptor , index ) ; code [ index + 1 ] = 0xFF ; code [ index + 2 ] = 0xFF ; index ++ ; } } } javaClass . Write ( outputZip ) ; } else { using ( var inputStream = javaFile . GetFileStream ( entry ) ) { StreamUtils . Copy ( inputStream , outputZip , buffer ) ; } } } } } } Console . WriteLine ( " " ) ; var patchedInfo = new MinecraftVersionInfo ( ) { ID = id , InheritsFrom = version . ID , Type = " " , MainClass = " " , MinimumLauncherVersion = 21 , } ; patchedVersion . WriteJsonFile ( patchedInfo ) ; Console . WriteLine ( " " ) ; return patchedVersion ; }
Patches the given minecraft version and returns the new patched version.
Patches the given minecraft version and returns the new patched version .
// Creates a new version // Searches for the next free directory. // Is this really necessary? // Creates the patched version // The copy buffer // Opens the java file // Creates the output file // Creates the output zip stream // Do not use 64 bit zip // Ignore the META-INF folder // Creates the output entry file // This is a class file // Loads the class // Gets the class info // Gets the method // Gets the method info // Gets the code attribute of the method // Change the code // Writes the class // Just copy the file // Creates the json file // Write the version json
None
version
MinecraftVersion
None
postfix
string
None