Пример #1
0
 void Start()
 {
     m_CurrLvlUrl   = GameSettings.Instance.LevelInt;
     m_DataInstance = this;
 }
Пример #2
0
        ///
        /// The primary code block that turns the custom level data into a format the game can read
        ///
        private void Make_Custom_Levels(string game_dir)
        {
            int           menulength    = 2112;
            List <string> src_filenames = new List <string>()
            {
                "lib/2e7b0500.pc", "lib/e0c51024.pc", "lib/f78b7d78.pc"
            };
            //these hashes are literally "customlevel#" hashed
            List <string> menu_hashes = new List <string>()
            {
                "1DCB06CE", "2D5C3C41", "273EA275", "EBA1CBD7", "1F8AD438", "DDF57F91", "9402A958", "FB3C6A42", "D4F0FAD2"
            };
            List <string> menu_names = new List <string>();
            //clear \out\ directory so that old level data is not stored anymore
            DirectoryInfo _out = new DirectoryInfo(@"out");

            foreach (string file in Directory.EnumerateFiles(@"out", "*.*", SearchOption.AllDirectories))
            {
                File.Delete(file);
            }
            foreach (DirectoryInfo dir in _out.GetDirectories())
            {
                dir.Delete();
            }

            //loop over each selected level
            foreach (LevelTraits level_name in LoadedLevels)
            {
                dynamic level_config = null;
                var     objs         = new List <dynamic>();
                var     obj_count    = 0;
                dynamic new_objs     = null;
                string  errorlist    = "";

                //iterate over each file in the custom level directory
                //filter out files that do not match the <file_types> list
                foreach (string filename in Directory.GetFiles(level_name.path))
                {
                    if (file_types.Contains(Path.GetFileName(filename).Split('_')[0]))
                    {
                        //read file and store JSON in dynamic object
                        try {
                            new_objs = JObject.Parse(Regex.Replace(File.ReadAllText(filename), @"#.*", ""), jo);
                        }
                        catch (Exception ex) {
                            errorlist += $"error parsing:\n{ex.Message} in file \"{Path.GetFileName(filename)}\" in level \"{level_name.name}\"\n\n";
                            continue;
                        }
                        //LevelLib contains important info for where the final level files go, so it gets put into its own object
                        if (new_objs.obj_type == "LevelLib")
                        {
                            level_config = new_objs;
                            obj_count--;
                        }
                        objs.Add(new_objs);
                        obj_count++;
                    }
                    //these file types require different processing to get the data
                    else if (file_special.Contains(Path.GetFileName(filename).Split('_')[0]))
                    {
                        try {
                            new_objs = JsonConvert.DeserializeObject(File.ReadAllText(filename));
                        }
                        catch (Exception ex) {
                            errorlist += $"error parsing:\n{ex.Message} in file \"{Path.GetFileName(filename)}\" in level \"{level_name.name}\"\n\n";
                            continue;
                        }
                        //spn_ and samp_ files contain multiple entries, inside the "multi":[] list
                        foreach (var _v in new_objs.items)
                        {
                            objs.Add(_v);
                            obj_count++;
                        }
                    }
                }
                //if errors exist, show the error, then return to stop further processing
                if (errorlist.Contains("error parsing"))
                {
                    MessageBox.Show(errorlist + "CUSTOM LEVELS NOT UPDATED", "Level load error");
                    return;
                }

                //var cache_filename = $@"out\{level_name.folder_name}\{level_config["cache_filename"]}";
                var cache_filename = $@"out\{level_name.folder_name}\{list_cache_filename[LoadedLevels.IndexOf(level_name)]}";
                Directory.CreateDirectory($@"out\{level_name.folder_name}");
                byte[] bytes;

                using (FileStream f = File.Open(cache_filename, FileMode.Create, FileAccess.Write, FileShare.None)) {
                    //write header information to level .pc file
                    bytes = File.ReadAllBytes(@"lib/header.objlib");
                    f.Write(bytes, 0, bytes.Length);

                    //write objlib path to level .pc file
                    //Write_String(f, (string)level_config["objlib_path"]);
                    Write_String(f, $"levels/custom/level{LoadedLevels.IndexOf(level_name)+1}.objlib");

                    //write "basic list of objects #1" information to level .pc file
                    bytes = File.ReadAllBytes(@"lib/obj_list_1.objlib");
                    f.Write(bytes, 0, bytes.Length);
                    //write to file the amount of objects that exists (after this number)
                    //this includes everything in "obj_list_2.objlib" (63) and obj_count
                    Write_Int(f, 63 + obj_count);
                    //write "basic list of objects #2" information to level .pc file
                    bytes = File.ReadAllBytes(@"lib/obj_list_2.objlib");
                    f.Write(bytes, 0, bytes.Length);
                    //write every object to the .pc file, hashing its name
                    foreach (var obj in objs)
                    {
                        if (obj_types.Contains((string)obj["obj_type"]))
                        {
                            if ((string)obj["obj_type"] != "Xfmer")
                            {
                                Write_Hash(f, (string)obj["obj_type"]);
                                Write_String(f, (string)obj["obj_name"]);
                            }
                            else
                            {
                                Write_Hash(f, (string)obj["obj_type"]);
                                Write_String(f, $"levels/custom/level{LoadedLevels.IndexOf(level_name) + 1}.xfm");
                            }
                        }
                    }

                    //bytes = File.ReadAllBytes($@"lib/obj_def_customlevel{LoadedLevels.IndexOf(level_name) + 1}.objlib");
                    bytes = File.ReadAllBytes($@"lib/obj_def_customlevel.objlib");
                    f.Write(bytes, 0, bytes.Length);
                    //iterate over every loaded object, and write its data to .pc file in specific formats.
                    //format is different per object. I myself am not exactly sure how it works, but this is how it's done
                    foreach (var obj in objs)
                    {
                        if (obj["obj_type"] == "SequinLeaf")
                        {
                            Write_Leaf(f, obj);
                        }
                        else if (obj["obj_type"] == "SequinLevel")
                        {
                            Write_Lvl_Header(f);
                            Write_Approach_Anim_Comp(f, obj);
                            Write_Lvl_Comp(f, obj);
                            Write_Lvl_Footer(f, obj);
                        }
                        else if (obj["obj_type"] == "SequinGate")
                        {
                            Write_Gate(f, obj);
                        }
                        else if (obj["obj_type"] == "SequinMaster")
                        {
                            Write_Master(f, obj);
                        }
                        else if (obj["obj_type"] == "EntitySpawner")
                        {
                            Write_Spn(f, obj);
                        }
                        else if (obj["obj_type"] == "Sample")
                        {
                            Write_Samp(f, obj);
                        }
                        else if (obj["obj_type"] == "Xfmer")
                        {
                            Write_Xfm_Header(f);
                            Write_Xfm_Comp(f, obj);
                        }
                    }

                    //close out file with footer info #1
                    bytes = File.ReadAllBytes(@"lib/footer_1.objlib");
                    f.Write(bytes, 0, bytes.Length);
                    //write file bpm
                    Write_Float(f, (float)level_config["bpm"]);
                    //close out file with footer info #2
                    bytes = File.ReadAllBytes(@"lib/footer_2.objlib");
                    f.Write(bytes, 0, bytes.Length);

                    src_filenames.Add(cache_filename);
                }


                //var config_cache_filename = $@"out\{level_name.folder_name}\{level_config["config_cache_filename"]}";
                var config_cache_filename = $@"out\{level_name.folder_name}\{list_config_cache_filename[LoadedLevels.IndexOf(level_name)]}";
                using (FileStream f = File.Open(config_cache_filename, FileMode.Create, FileAccess.Write, FileShare.None)) {
                    Write_Int(f, 9);
                    Write_Int(f, level_config["level_sections"].Count);
                    foreach (var level_section in level_config["level_sections"])
                    {
                        Write_String(f, (string)level_section);
                    }
                    Write_Color(f, level_config["rails_color"]);
                    Write_Color(f, level_config["rails_glow_color"]);
                    Write_Color(f, level_config["path_color"]);
                    Write_Color(f, level_config["joy_color"]);

                    src_filenames.Add(config_cache_filename);
                }
                menu_names.Add(level_name.name);
                menulength += level_name.name.Length + 1;
            }

            //Update menu names
            using (FileStream f = File.Open(@"lib\2e7b0500.pc", FileMode.Create, FileAccess.Write, FileShare.None)) {
                byte[] bytes;
                int    pos = 2112;
                //write menu headers/pointers
                Write_Int(f, 6);
                Write_Int(f, 174);
                Write_Int(f, menulength + ((9 - menu_names.Count) * ("no level".Length + 1)));
                //write all menu strings. Don't edit this
                bytes = File.ReadAllBytes(@"lib/menu1.objlib");
                f.Write(bytes, 0, bytes.Length);
                //user set level names
                for (int x = 0; x < 9; x++)
                {
                    if (x < menu_names.Count)
                    {
                        f.Write(Encoding.ASCII.GetBytes(menu_names[x]), 0, menu_names[x].Length);
                    }
                    else
                    {
                        f.Write(Encoding.ASCII.GetBytes("no level"), 0, "no level".Length);
                    }
                    f.Write(new byte[] { 0x00 }, 0, 1);
                }
                //write menu hashes and positions. Don't edit this
                bytes = File.ReadAllBytes(@"lib/menu2.objlib");
                f.Write(bytes, 0, bytes.Length);

                //write custom hashes and string position in file.
                for (int x = 0; x < 9; x++)
                {
                    Write_Hex(f, menu_hashes[x]);
                    Write_Int(f, pos);
                    if (x < menu_names.Count)
                    {
                        pos += menu_names[x].Length + 1;
                    }
                    else
                    {
                        pos += "no level".Length + 1;
                    }
                }
            }

            //copy new .pc files to game directory
            foreach (string src_filename in src_filenames)
            {
                File.Copy(src_filename, $@"{game_dir}\cache\{Path.GetFileName(src_filename)}", true);
            }
        }