Ejemplo n.º 1
0
        /// <summary>
        /// Writes the json file
        /// </summary>
        /// <param name="path"></param>
        /// <param name="info"></param>
        public static void WriteJsonFile(string path, MinecraftVersionInfo info)
        {
            // Opens the json file
            using (var stream = new FileStream(path, FileMode.Create))
            {
                using (var streamWriter = new StreamWriter(stream))
                {
                    // Creates the json writer
                    using (var writer = new JsonTextWriter(streamWriter))
                    {
                        writer.Formatting = Formatting.Indented;

                        writer.WriteStartObject();
                        writer.WritePropertyName("id");
                        writer.WriteValue(info.ID);

                        if (!string.IsNullOrEmpty(info.InheritsFrom))
                        {
                            writer.WritePropertyName("inheritsFrom");
                            writer.WriteValue(info.InheritsFrom);
                        }

                        if (!string.IsNullOrEmpty(info.Type))
                        {
                            writer.WritePropertyName("type");
                            writer.WriteValue(info.Type);
                        }

                        if (!string.IsNullOrEmpty(info.MainClass))
                        {
                            writer.WritePropertyName("mainClass");
                            writer.WriteValue(info.MainClass);
                        }

                        if (info.MinimumLauncherVersion != 0)
                        {
                            writer.WritePropertyName("minimumLauncherVersion");
                            writer.WriteValue(info.MinimumLauncherVersion.ToString());
                        }

                        // Writes the empty arguments object.
                        writer.WritePropertyName("arguments");
                        writer.WriteStartObject();
                        writer.WriteEndObject();

                        // Prevents the launcher from redownloading the jar file
                        // by creating an empty downloads object.
                        writer.WritePropertyName("downloads");
                        writer.WriteStartObject();
                        writer.WriteEndObject();

                        writer.WriteEndObject();
                    }
                }
            }
        }
Ejemplo n.º 2
0
 /// <summary>
 /// Writes the json file
 /// </summary>
 /// <param name="info"></param>
 public void WriteJsonFile(MinecraftVersionInfo info)
 {
     WriteJsonFile(PathJson, info);
 }
Ejemplo n.º 3
0
        /// <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>
        private static MinecraftVersion Patch(MinecraftVersion version, string postfix)
        {
            Console.WriteLine("Start pathching '{0}'...", version.ID);
            Console.WriteLine("------------------------------------------------------");

            // Creates a new version
            var parentPath = Path.GetDirectoryName(version.Path);

            // Searches for the next free directory.
            // Is this really necessary?
            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);

            // Creates the patched version
            var patchedVersion = new MinecraftVersion(path);

            // The copy buffer
            var buffer = new byte[1024 * 8];

            // Opens the java file
            using (var javaFile = version.OpenJavaFile())
            {
                // Creates the output file
                using (var output = new FileStream(patchedVersion.PathJar, FileMode.Create))
                {
                    // Creates the output zip stream
                    using (var outputZip = new ZipOutputStream(output))
                    {
                        // Do not use 64 bit zip
                        outputZip.UseZip64 = UseZip64.Off;

                        var files = javaFile.Zip.Count;
                        for (int i = 0; i < files; i++)
                        {
                            var entry = javaFile.Zip[i];


                            // Ignore the META-INF folder
                            if (entry.Name.Contains("META-INF/"))
                            {
                                continue;
                            }

                            // Creates the output entry file
                            var outputEntry = new ZipEntry(entry.Name);
                            outputEntry.DateTime = entry.DateTime;
                            outputEntry.Size     = entry.Size;
                            outputZip.PutNextEntry(outputEntry);

                            // This is a class file
                            if (Path.GetExtension(entry.Name) == ".class")
                            {
                                // Loads the class
                                var javaClass = javaFile.GetClass(entry);

                                // Gets the class info
                                var javaClassInfo = javaClass.GetConstant <JavaConstantClassInfo>(javaClass.ThisClass);
                                var javaClassName = javaClass.GetConstantUtf8(javaClassInfo.NameIndex);

                                // Gets the method
                                var javaMethod = javaClass.GetMethod("keyPressed");


                                if (javaMethod != null)
                                {
                                    // Gets the method info
                                    var javaMethodName       = javaClass.GetConstantUtf8(javaMethod.NameIndex);
                                    var javaMethodDescriptor = javaClass.GetConstantUtf8(javaMethod.DescriptorIndex);

                                    // Gets the code attribute of the method
                                    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);

                                            // Change the code
                                            code[index + 1] = 0xFF;
                                            code[index + 2] = 0xFF;


                                            index++;
                                        }
                                    }
                                }

                                // Writes the class
                                javaClass.Write(outputZip);
                            }
                            else
                            {
                                // Just copy the file
                                using (var inputStream = javaFile.GetFileStream(entry))
                                {
                                    StreamUtils.Copy(inputStream, outputZip, buffer);
                                }
                            }
                        }
                    }
                }
            }

            Console.WriteLine("Creating json file...");

            // Creates the json file
            var patchedInfo = new MinecraftVersionInfo()
            {
                ID                     = id,
                InheritsFrom           = version.ID,
                Type                   = "custom",
                MainClass              = "net.minecraft.client.main.Main",
                MinimumLauncherVersion = 21,
            };

            // Write the version json
            patchedVersion.WriteJsonFile(patchedInfo);

            Console.WriteLine("Version got patched!");

            return(patchedVersion);
        }