示例#1
0
        internal void SaveLibrary(string filepath, List <J2TFile> Tilesets, int numberOfExtraDataLevels, WeaponsForm.ExtendedWeapon[] customWeapons)
        {
            var           encoding          = J2LFile.FileEncoding;
            List <string> RequiredFilenames = new List <string>();
            bool          weaponLibrary     = false;

            foreach (var cw in customWeapons)
            {
                if (cw != null)
                {
                    RequiredFilenames.Add(cw.LibraryFilename);
                    weaponLibrary = true;
                }
            }

            string AngelscriptLibraryFilename = "MLLE-Include-" + CurrentMLLEData5VersionString + (!weaponLibrary ? "" : "w") + ".asc";

            using (BinaryWriter binwriter = new BinaryWriter(File.Open(Path.Combine(Path.GetDirectoryName(filepath), AngelscriptLibraryFilename), FileMode.Create, FileAccess.Write), encoding)) {
                binwriter.Write(encoding.GetBytes("//"));
                var libraryFileAsBytes = encoding.GetBytes(string.Format(
                                                               AngelscriptLibrary,
                                                               AngelscriptLibraryFilename,
                                                               !weaponLibrary ? "" : AngelscriptLibraryWeaponsPortion1,
                                                               !weaponLibrary ? "" : AngelscriptLibraryWeaponsPortion2,
                                                               !weaponLibrary ? "" : AngelscriptLibraryWeaponsPortion3,
                                                               !weaponLibrary ? "" : AngelscriptLibraryWeaponsPortion4
                                                               ));
                CRC32 CRCCalculator = new CRC32();
                CRCCalculator.SlurpBlock(libraryFileAsBytes, 0, libraryFileAsBytes.Length);
                binwriter.Write(encoding.GetBytes(((uint)CRCCalculator.Crc32Result).ToString() + "\r\n"));
                binwriter.Write(libraryFileAsBytes);
            }

            string scriptFilepath = Path.ChangeExtension(filepath, ".j2as");
            string fileContents   = "";

            if (File.Exists(scriptFilepath))
            {
                fileContents = System.IO.File.ReadAllText(scriptFilepath, encoding);
            }
            RequiredFilenames.Add(Path.GetFileName(filepath));
            for (int i = 1; i < Tilesets.Count; ++i)
            {
                RequiredFilenames.Add(Tilesets[i].FilenameOnly);
            }
            int extraDataLevelID = 0;

            for (extraDataLevelID = 0; extraDataLevelID < numberOfExtraDataLevels; ++extraDataLevelID)
            {
                RequiredFilenames.Add(Path.GetFileName(GetExtraDataLevelFilepath(filepath, extraDataLevelID)));
            }
            foreach (string fn in RequiredFilenames)
            {
                string pragma = GetPragmaRequire(fn);
                if (!fileContents.Contains(pragma))
                {
                    fileContents = pragma + TagForProgrammaticallyAddedLines + fileContents;
                }
                if (fn.EndsWith("asc", System.StringComparison.InvariantCultureIgnoreCase))
                {
                    pragma = GetPragmaInclude(fn);
                    if (!fileContents.Contains(pragma))
                    {
                        fileContents = pragma + TagForProgrammaticallyAddedLines + fileContents;
                    }
                }
            }
            while (true) //remove extra such pragmas/files if the number of layers has decreased since the last time this level was saved
            {
                string extraFilepath = GetExtraDataLevelFilepath(filepath, extraDataLevelID++);
                File.Delete(extraFilepath);
                string pragma = GetPragmaRequire(Path.GetFileName(extraFilepath));
                if (fileContents.Contains(pragma))
                {
                    fileContents = new Regex("^[^\\n]*" + pragma + "\\s*?\\r?\\n?", RegexOptions.Multiline).Replace(fileContents, "");
                }
                else
                {
                    break;
                }
            }
            fileContents = "#include \"" + AngelscriptLibraryFilename + "\"" + TagForProgrammaticallyAddedLines + fileContents;
            Regex  setupPattern     = new Regex(@"MLLE\s*::\s*Setup\s*\([^;]*\)\s*;");
            string desiredSetupCall = "MLLE::Setup(";

            if (weaponLibrary)
            {
                desiredSetupCall += "array<MLLEWeaponApply@> = {";
                for (int i = 0; i < 9; ++i)
                {
                    WeaponsForm.ExtendedWeapon cw = customWeapons[i];
                    if (cw != null)
                    {
                        desiredSetupCall += cw.Initialization;
                    }
                    else
                    {
                        desiredSetupCall += "null";
                    }
                    if (i < 8)
                    {
                        desiredSetupCall += ", ";
                    }
                }
                desiredSetupCall += "}";
            }
            desiredSetupCall += ");";
            Match match = setupPattern.Match(fileContents);

            if (!match.Success)
            {
                fileContents = "const bool MLLESetupSuccessful = " + desiredSetupCall + TagForProgrammaticallyAddedLines + fileContents;
            }
            else if (match.Value != desiredSetupCall)
            {
                fileContents = setupPattern.Replace(fileContents, desiredSetupCall);
            }

            bool[] hooksNeeded = WeaponHookSpecs.Select(ss => weaponLibrary && customWeapons.Any(cw => cw != null && new Regex("\\b" + ss[1] + "\\b", RegexOptions.IgnoreCase).Match(cw.Hooks).Success)).ToArray();
            hooksNeeded[3] = weaponLibrary; //onDrawAmmo is used by ALL custom weapons

            for (int specID = 0; specID < WeaponHookSpecs.Length; ++specID)
            {
                string[] spec = WeaponHookSpecs[specID];

                Regex weaponHookCallFindRegex = new Regex(@"(return\s+)?MLLE\s*::\s*WeaponHook\s*\.\s*" + spec[2] + @"\s*\([^;]*\)(\s*;)?");

                string functionPattern = "(" + spec[0] + @"\s+" + spec[1] + @"\s*\(\s*";
                for (int paramStringID = 3; paramStringID < spec.Length; paramStringID += 2)
                {
                    functionPattern += spec[paramStringID].Replace(" ", @"\s*") + @"\s*(\S+)\s*";
                    if (paramStringID + 2 < spec.Length)
                    {
                        functionPattern += @",\s*";
                    }
                }
                functionPattern += @"\)[^{]*{)"; //e.g. a pattern to match "void onMain() {"

                if (hooksNeeded[specID])
                {
                    if (!weaponHookCallFindRegex.Match(fileContents).Success) //weaponhook call not being made
                    {
                        string weaponhookMethodCall = "\r\n\t" + (spec[0] == "void" ? "" : "return ") + "MLLE::WeaponHook." + spec[2] + "(";
                        for (int paramStringID = 3; paramStringID < spec.Length; paramStringID += 2)
                        {
                            weaponhookMethodCall += "$" + ((paramStringID + 1) / 2).ToString();
                            if (paramStringID + 2 < spec.Length)
                            {
                                weaponhookMethodCall += ", ";
                            }
                        }
                        weaponhookMethodCall += ");"; //e.g. "WeaponHook::processMain();"

                        Regex functionRegex = new Regex(functionPattern);
                        match = functionRegex.Match(fileContents);
                        if (match.Success) //hook function already exists
                        {
                            fileContents = functionRegex.Replace(fileContents, "$1" + weaponhookMethodCall);
                        }
                        else
                        { //add everything from scratch
                            string functionToAdd = "\r\n" + spec[0] + " " + spec[1] + "(";
                            for (int paramStringID = 3; paramStringID < spec.Length; paramStringID += 2)
                            {
                                functionToAdd       += spec[paramStringID].Replace(" ", "") + " " + spec[paramStringID + 1];
                                weaponhookMethodCall = weaponhookMethodCall.Replace("$" + ((paramStringID + 1) / 2).ToString(), spec[paramStringID + 1]);
                                if (paramStringID + 2 < spec.Length)
                                {
                                    functionToAdd += ", ";
                                }
                            }
                            functionToAdd += ") {" + weaponhookMethodCall + "\r\n}\r\n";

                            fileContents += functionToAdd;
                        }
                    }
                }
                else //hook NOT needed
                {
                    fileContents = new Regex(functionPattern + @"[\s;]*}\r?\n?").Replace(weaponHookCallFindRegex.Replace(fileContents, ""), ""); //remove the method call, then remove the hook function it was in if that hook is now totally empty
                }
            }
            System.IO.File.WriteAllText(scriptFilepath, fileContents, encoding);
        }
示例#2
0
        internal bool CreateData5Section(out byte[] Data5, out WeaponsForm.ExtendedWeapon[] CustomWeapons, List <J2TFile> Tilesets, List <Layer> Layers)
        {
            Data5         = null;
            CustomWeapons = new WeaponsForm.ExtendedWeapon[9];
            var data5header = new MemoryStream();

            using (MemoryStream data5body = new MemoryStream())
                using (BinaryWriter data5writer = new BinaryWriter(data5header, J2LFile.FileEncoding))
                    using (BinaryWriter data5bodywriter = new BinaryWriter(data5body, J2LFile.FileEncoding))
                    {
                        data5writer.Write(MLLEData5MagicString.ToCharArray());
                        data5writer.Write(CurrentMLLEData5Version);

                        data5bodywriter.Write(IsSnowing);
                        data5bodywriter.Write(IsSnowingOutdoorsOnly);
                        data5bodywriter.Write(SnowingIntensity);
                        data5bodywriter.Write((byte)SnowingType);
                        data5bodywriter.Write(WarpsTransmuteCoins);
                        data5bodywriter.Write(DelayGeneratedCrateOrigins);
                        data5bodywriter.Write(Echo);
                        data5bodywriter.Write(DarknessColor.ToArgb());
                        data5bodywriter.Write(WaterChangeSpeed);
                        data5bodywriter.Write((byte)WaterInteraction);
                        data5bodywriter.Write(WaterLayer);
                        data5bodywriter.Write((byte)WaterLighting);
                        data5bodywriter.Write(WaterLevel);
                        data5bodywriter.Write(WaterGradientStart.ToArgb());
                        data5bodywriter.Write(WaterGradientStop.ToArgb());

                        data5bodywriter.Write(Palette != null);
                        if (Palette != null)
                        {
                            Palette.WriteLEVStyle(data5bodywriter);
                        }

                        foreach (byte[] remappings in ColorRemappings)
                        {
                            if (remappings == null)
                            {
                                data5bodywriter.Write(false);
                            }
                            else
                            {
                                data5bodywriter.Write(true);
                                for (int i = 0; i < remappings.Length; ++i)
                                {
                                    data5bodywriter.Write(remappings[i]);
                                }
                            }
                        }

                        data5bodywriter.Write((byte)(Tilesets.Count - 1));
                        for (int tilesetID = 1; tilesetID < Tilesets.Count; ++tilesetID) //Tilesets[0] is already mentioned in Data1, after all
                        {
                            var tileset = Tilesets[tilesetID];
                            data5bodywriter.Write(Path.ChangeExtension(tileset.FilenameOnly, ".j2t")); //convert "J2T" to "j2t" so JJ2+ doesn't reject the jjTilesFromTileset call
                            data5bodywriter.Write((ushort)tileset.FirstTile);
                            data5bodywriter.Write((ushort)tileset.TileCount);
                            byte[] remappings = tileset.ColorRemapping;
                            data5bodywriter.Write(remappings != null);
                            if (remappings != null)
                            {
                                for (int i = 0; i < remappings.Length; ++i)
                                {
                                    data5bodywriter.Write(remappings[i]);
                                }
                            }
                        }

                        data5bodywriter.Write((uint)Layers.Count);
                        foreach (Layer layer in Layers)
                        {
                            data5bodywriter.Write((sbyte)layer.id);
                            data5bodywriter.Write(layer.Name);
                            data5bodywriter.Write(layer.Hidden);
                            data5bodywriter.Write(layer.SpriteMode);
                            data5bodywriter.Write(layer.SpriteParam);
                            data5bodywriter.Write(layer.RotationAngle);
                            data5bodywriter.Write(layer.RotationRadiusMultiplier);
                        }

                        int levelTileCount = Tilesets.Sum(ts => (int)ts.TileCount);
                        foreach (byte[][] images in new byte[][][] { TileImages, TileMasks })
                        {
                            int numberOfImages = images.Take(levelTileCount).Count(it => it != null);
                            data5bodywriter.Write((ushort)numberOfImages);
                            if (numberOfImages > 0)
                            {
                                for (int i = 1; i < levelTileCount; ++i)
                                {
                                    byte[] image = images[i];
                                    if (image != null)
                                    {
                                        data5bodywriter.Write((ushort)i);
                                        data5bodywriter.Write(image);
                                    }
                                }
                            }
                        }

                        for (int weaponID = 0; weaponID < Weapons.Length; ++weaponID)
                        {
                            Weapon weapon        = Weapons[weaponID];
                            Weapon defaultWeapon = WeaponDefaults[weaponID];
                            bool   isGun8InSlot8 = weaponID == 7 && weapon.Name == "Gun8"; //hardcoded laxer standards... parameter need not match
                            bool   isCustom      = !isGun8InSlot8 && !(weapon.Name.Equals(defaultWeapon.Name) && weapon.Options.Skip(Weapon.NumberOfCommonOptions).SequenceEqual(defaultWeapon.Options.Skip(Weapon.NumberOfCommonOptions)));
                            data5bodywriter.Write(isCustom);
                            int[] options = weapon.Options;
                            data5bodywriter.Write(options[0]);
                            data5bodywriter.Write((byte)options[1]);
                            data5bodywriter.Write(options[2] != 0);
                            data5bodywriter.Write((byte)options[3]);
                            data5bodywriter.Write((byte)options[4]);
                            data5bodywriter.Write((byte)options[5]);
                            if (weaponID == 6)
                            {
                                data5bodywriter.Write(Gun7Crate);
                            }
                            else if (weaponID == 7)
                            {
                                data5bodywriter.Write(Gun8Crate);
                            }
                            else if (weaponID == 8)
                            {
                                data5bodywriter.Write(Gun9Crate);
                            }
                            if (isGun8InSlot8)
                            {
                                data5bodywriter.Write((byte)options[Weapon.NumberOfCommonOptions]);
                            }
                            else if (isCustom)
                            {
                                data5bodywriter.Write(weapon.Name);
                                var extendedWeapon = WeaponsForm.GetAllAvailableWeapons().Find(w => w.Name == weapon.Name);
                                if (extendedWeapon == null)
                                {
                                    MessageBox.Show(String.Format("Sorry, the MLLE \"Weapons\" folder did not include any .ini file defining a weapon with the name \"{0}.\"", weapon.Name), "Weapon not found", MessageBoxButtons.OK, MessageBoxIcon.Error);
                                    return(false);
                                }
                                CustomWeapons[weaponID] = extendedWeapon;
                                data5bodywriter.Write(extendedWeapon.OptionTypes.Skip(Weapon.NumberOfCommonOptions).Select(o => o == WeaponsForm.ExtendedWeapon.oTypes.Int ? sizeof(int) : sizeof(byte)).Sum());
                                for (int optionID = Weapon.NumberOfCommonOptions; optionID < options.Length; ++optionID)
                                {
                                    switch (extendedWeapon.OptionTypes[optionID])
                                    {
                                    case WeaponsForm.ExtendedWeapon.oTypes.Bool:
                                        data5bodywriter.Write(options[optionID] != 0);
                                        break;

                                    case WeaponsForm.ExtendedWeapon.oTypes.Dropdown:
                                        data5bodywriter.Write((byte)options[optionID]);
                                        break;

                                    case WeaponsForm.ExtendedWeapon.oTypes.Int:
                                    default:
                                        data5bodywriter.Write(options[optionID]);
                                        break;
                                    }
                                }
                            }
                        }

                        var data5bodycompressed = ZlibStream.CompressBuffer(data5body.ToArray());
                        data5writer.Write((uint)data5bodycompressed.Length);
                        data5writer.Write((uint)data5body.Length);
                        data5writer.Write(data5bodycompressed);
                    }
            Data5 = data5header.ToArray();
            return(true);
        }