Beispiel #1
0
        private Level(BinaryReader reader) : this()
        {
            ID = reader.ReadInt32();
            var nameLength = reader.ReadInt32();

            Name      = Encoding.UTF8.GetString(reader.ReadBytes(nameLength));
            SPlusTime = reader.ReadUInt16();
            STime     = reader.ReadUInt16();
            ATime     = reader.ReadUInt16();
            BTime     = reader.ReadUInt16();
            CTime     = reader.ReadUInt16();
            CheckTime();
            var prismsCount = reader.ReadInt16();

            Size = new Size3D(reader);
            #region Boring verifying
            var temp = reader.ReadUInt16();
            if (Temp1 != temp)
            {
                Warning.WriteLine(string.Format(Localization.LevelInvalidArgument, temp, Temp1, "unknown_ushort_1"));
            }
            temp = reader.ReadUInt16();
            if (Temp2 != temp)
            {
                Warning.WriteLine(string.Format(Localization.LevelInvalidArgument, temp, Temp2, "unknown_ushort_2"));
            }
            ushort width = reader.ReadUInt16(), length = reader.ReadUInt16();
            var    legacyMinimapValid = true;
            if (LegacyMinimapSize.Width != width)
            {
                Warning.WriteLine(string.Format(Localization.LevelInvalidArgument, width, LegacyMinimapSize.Width,
                                                "unknown_ushort_3"));
                legacyMinimapValid = false;
            }
            if (LegacyMinimapSize.Length != length)
            {
                Warning.WriteLine(string.Format(Localization.LevelInvalidArgument, width, LegacyMinimapSize.Length,
                                                "unknown_ushort_4"));
                legacyMinimapValid = false;
            }
            if (!legacyMinimapValid)
            {
                Warning.WriteLine(Localization.LevelLegacyMinimapMalformed);
            }
            var tempByte = reader.ReadByte();
            if (tempByte != 10)
            {
                Warning.WriteLine(string.Format(Localization.LevelInvalidArgument, temp, 10, "unknown_byte_1"));
            }
            temp = reader.ReadUInt16();
            if (Size.Length - 1 != temp)
            {
                Warning.WriteLine(string.Format
                                      (Localization.LevelInvalidArgument, temp, Size.Length - 1, "unknown_ushort_5"));
            }
            temp = reader.ReadUInt16();
            if (0 != temp)
            {
                Warning.WriteLine(string.Format(Localization.LevelInvalidArgument, temp, 0, "unknown_ushort_6"));
            }
            #endregion
            if (legacyMinimapValid)
            {
                LegacyMinimap = new Flat(reader, LegacyMinimapSize);
            }
            else
            {
                LegacyMinimap = new Flat(LegacyMinimapSize);
                reader.ReadBytes((width * length + 7) / 8);
            }
            CollisionMap = new Cube(reader, Size);
            SpawnPoint   = new Point3D16(reader);
            Zoom         = reader.ReadInt16();
            if (Zoom < 0)
            {
                Value        = reader.ReadInt16();
                ValueIsAngle = reader.ReadBoolean();
            }
            ExitPoint = new Point3D16(reader);
            var count = reader.ReadUInt16();
            for (var i = 0; i < count; i++)
            {
                MovingPlatforms.Add(new MovingPlatform(MovingPlatforms, reader));
            }
            count = reader.ReadUInt16();
            for (var i = 0; i < count; i++)
            {
                Bumpers.Add(new Bumper(Bumpers, reader));
            }
            count = reader.ReadUInt16();
            for (var i = 0; i < count; i++)
            {
                FallingPlatforms.Add(new FallingPlatform(this, reader));
            }
            count = reader.ReadUInt16();
            for (var i = 0; i < count; i++)
            {
                Checkpoints.Add(new Checkpoint(reader));
            }
            count = reader.ReadUInt16();
            for (var i = 0; i < count; i++)
            {
                CameraTriggers.Add(new CameraTrigger(reader));
            }
            count = reader.ReadUInt16();
            for (var i = 0; i < count; i++)
            {
                Prisms.Add(new Prism(reader));
            }
            if (count != prismsCount)
            {
                Warning.WriteLine(string.Format
                                      (Localization.LevelInvalidArgument, prismsCount, count, "prisms_count"));
            }
            if ((count = reader.ReadUInt16()) > 0)
            {
                Warning.WriteLine(string.Format(Localization.DeprecatedElement, "Fan"));
            }
            for (var i = 0; i < count; i++)
            {
                Fans.Add(new Fan(reader));
            }
            Buttons = new Buttons(this, reader);
            count   = reader.ReadUInt16();
            for (var i = 0; i < count; i++)
            {
                OtherCubes.Add(new OtherCube(this, reader));
            }
            count = reader.ReadUInt16();
            for (var i = 0; i < count; i++)
            {
                Resizers.Add(new Resizer(this, reader));
            }
            if ((count = reader.ReadUInt16()) > 0)
            {
                Warning.WriteLine(string.Format(Localization.DeprecatedElement, "MiniBlock"));
            }
            for (var i = 0; i < count; i++)
            {
                MiniBlocks.Add(new MiniBlock(reader));
            }
            ModelTheme = Theme = reader.ReadByte();
            MusicJava  = reader.ReadByte();
            Music      = reader.ReadByte();
            foreach (var button in Buttons)
            {
                if (button.IsMoving)
                {
                    button.MovingPlatformID.Name.DoNothing();
                }
                foreach (var e in button.Events)
                {
                    Buttons.BlockEvents[e].ID.Name.DoNothing();
                }
            }
            foreach (var cube in OtherCubes)
            {
                cube.MovingBlockSync.Name.DoNothing();
                cube.DarkCubeMovingBlockSync?.Name.DoNothing();
            }
        }
Beispiel #2
0
        public OtherCube(Level parent, XElement element)
        {
            element.GetAttributeValue(out PositionTrigger, "PositionTrigger");
            var id   = element.GetAttributeValue("MovingBlockSync");
            var sync = id == null ? new IDReference <MovingPlatform>(parent.MovingPlatforms, -1)
                                  : new IDReference <MovingPlatform>(parent.MovingPlatforms, id);

            element.GetAttributeValueWithDefault(out DarkCubeRadius, "Radius");
            element.GetAttributeValue(out PositionCube, "PositionCube");
            foreach (var e in element.Elements())
            {
                try
                {
                    KeyEvents.Add(new KeyEvent(e));
                }
                catch
                {
                    if (!e.Name.LocalName.Equals("MovingPlatform", StringComparison.InvariantCultureIgnoreCase) &&
                        !e.Name.LocalName.Equals("Button", StringComparison.InvariantCultureIgnoreCase))
                    {
                        Warning.WriteLine(string.Format(Localization.UnrecognizedChildElement, e.Name, element.Name));
                    }
                }
            }
            if (element.Name == "OtherCube")
            {
                MovingBlockSync = sync;
                var mode          = element.GetAttributeValueWithDefault("Mode", OtherCubeMode.AutoHide);
                var moveDirection = element.GetAttributeValueWithDefault("MoveDirection", GetDefaultDirection(mode));
                if (mode == OtherCubeMode.Hole)
                {
                    PositionTrigger -= moveDirection;
                }
                AddHelper(parent, mode, PositionTrigger, moveDirection, element);
                if (DarkCubeRadius.Equals(default(Point2D8)))
                {
                    return;
                }
                var radius = DarkCubeRadius;
                DarkCubeRadius = default(Point2D8);
                for (var x = -radius.X; x <= radius.X; x++)
                {
                    for (var y = -radius.Y; y <= radius.Y; y++)
                    {
                        if (x != 0 || y != 0)
                        {
                            var position = PositionTrigger + new Point3D16((short)x, (short)y, 0);
                            parent.OtherCubes.Add(new OtherCube
                            {
                                PositionTrigger = position,
                                MovingBlockSync = MovingBlockSync,
                                PositionCube    = PositionCube,
                                KeyEvents       = KeyEvents
                            });
                            AddHelper(parent, mode, position, moveDirection, element);
                        }
                    }
                }
            }
            else
            {
                MovingBlockSync         = new IDReference <MovingPlatform>(parent.MovingPlatforms, -2);
                DarkCubeMovingBlockSync = sync;
            }
        }
Beispiel #3
0
        private Level(string path) : this()
        {
            var element = XHelper.Load(path + ".xml").GetElement("Level");

            ID   = element.GetAttributeValue <int>("ID");
            Name = element.GetAttributeValueWithDefault("Name", string.Empty);
            var thresholds = element.GetAttributeValueWithDefault("TimeThresholds", "1,2,3,4,5").Split(',')
                             .Select(str => ushort.Parse(str.Trim())).ToArray();

            SPlusTime = thresholds[0];
            STime     = thresholds[1];
            ATime     = thresholds[2];
            BTime     = thresholds[3];
            CTime     = thresholds[4];
            CheckTime();
            Size          = element.GetAttributeValue <Size3D>("Size");
            LegacyMinimap = new Flat(path + ".png", LegacyMinimapSize);
            CollisionMap  = new Cube(path + ".{0}.png", Size);
            SpawnPoint    = element.GetAttributeValue <Point3D16>("SpawnPoint");
            ExitPoint     = element.GetAttributeValue <Point3D16>("ExitPoint");
            Theme         = element.GetAttributeValueWithDefault <byte>("Theme");
            ModelTheme    = element.GetAttributeValueWithDefault("ModelTheme", Theme);
            MusicJava     = element.GetAttributeValueWithDefault <byte>("MusicJava");
            Music         = element.GetAttributeValueWithDefault("Music", (byte)6);
            Zoom          = element.GetAttributeValueWithDefault("Zoom", (short)-1);
            var advanced = true;

            if (ValueIsAngle = element.AttributeCaseInsensitive("Angle") != null)
            {
                Value = element.GetAttributeValueWithDefault <short>("Angle", 22);
                if (element.AttributeCaseInsensitive("FieldOfView") != null)
                {
                    Warning.WriteLine(string.Format(Localization.FieldOfViewIgnored, "Level"));
                }
            }
            else if (element.AttributeCaseInsensitive("FieldOfView") != null)
            {
                Value = element.GetAttributeValueWithDefault <short>("FieldOfView", 22);
            }
            else if (Zoom < 0)
            {
                Value = 22;
            }
            else
            {
                advanced = false;
            }
            if (Zoom >= 0 && advanced)
            {
                Warning.WriteLine(string.Format(Localization.AdvancedCameraModeDisabled,
                                                "Level", "@Angle, @FieldOfView"));
            }
            Buttons = new Buttons(this);
            foreach (var e in element.Elements())
            {
                switch (e.Name.LocalName.ToLower())
                {
                case "movingplatform":
                    MovingPlatforms.Add(new MovingPlatform(MovingPlatforms, e));
                    break;

                case "bumper":
                    Bumpers.Add(new Bumper(Bumpers, e));
                    break;

                case "fallingplatform":
                    FallingPlatforms.Add(new FallingPlatform(this, e));
                    break;

                case "checkpoint":
                    Checkpoints.Add(new Checkpoint(e));
                    break;

                case "cameratrigger":
                    CameraTriggers.Add(new CameraTrigger(e));
                    break;

                case "prism":
                    Prisms.Add(new Prism(e));
                    break;

                case "fan":
                    Fans.Add(new Fan(e));
                    Warning.WriteLine(string.Format(Localization.DeprecatedElement, "Fan"));
                    break;

                case "button":
                case "buttonsequence":
                    // ReSharper disable once ObjectCreationAsStatement
                    new Button(Buttons, e);
                    break;

                case "othercube":
                case "darkcube":
                    OtherCubes.Add(new OtherCube(this, e));
                    break;

                case "resizergrow":
                case "resizershrink":
                    Resizers.Add(new Resizer(this, e));
                    break;

                case "miniblock":
                    MiniBlocks.Add(new MiniBlock(e));
                    Warning.WriteLine(string.Format(Localization.DeprecatedElement, "MiniBlock"));
                    break;

                default:
                    Warning.WriteLine(string.Format(Localization.UnrecognizedChildElement, e.Name, "Level"));
                    break;
                }
            }
        }
Beispiel #4
0
        public static Tuple <Exception, string, List <FileEntry> > Compile(bool exFormat, string file,
                                                                           string directory = null)
        {
            var list     = new List <FileEntry>();
            var fileName = Path.GetFileNameWithoutExtension(file);

            if (string.IsNullOrWhiteSpace(directory))
            {
                directory = Path.GetDirectoryName(file);
            }
            string inputPath  = Path.Combine(Path.GetDirectoryName(file), fileName),
                   outputPath = Path.Combine(directory, fileName);

            Warning.Start();
            try
            {
                switch ((Path.GetExtension(file) ?? string.Empty).ToLowerInvariant())
                {
                case ".bin":
                    switch (fileName.ToLowerInvariant())
                    {
                    case "cos":
                        var array = new short[181];
                        using (var stream = File.OpenRead(file))
                            using (var reader = new BinaryReader(stream))
                                for (var i = 0; i <= 180; i++)
                                {
                                    array[i] = reader.ReadInt16();
                                }
                        File.WriteAllText(outputPath += ".txt",
                                          string.Join(Environment.NewLine, array.Select(value => value / 256.0)));
                        list.Add(new FileEntry(outputPath, "cos.txt"));
                        break;

                    case "font":
                        DecompileFont(file, ref outputPath);
                        list.Add(new FileEntry(outputPath, "font.xml"));
                        break;

                    default:
                    {
                        var index = 0;
                        foreach (var path in Level.CreateFromCompiled(file).Decompile(outputPath))
                        {
                            list.Add(new FileEntry(path, index == 0 ? "level.xml"
                                        : index == 1 ? "level.png" : "level.z.png"));
                            index++;
                        }
                        break;
                    }
                    }
                    break;

                case ".xml":
                    var root = XHelper.Load(file).Elements().First();
                    switch (root.Name.LocalName.ToLowerInvariant())
                    {
                    case "level":
                    {
                        var index = 0;
                        foreach (var path in Level.CreateFromDecompiled(inputPath)
                                 .Compile(outputPath + ".bin"))
                        {
                            list.Add(new FileEntry(path, index == 0 ? "level.bin" : "model.eso"));
                            index++;
                        }
                        break;
                    }

                    case "animation":
                        AssetHelper.ParseEan(root, fileName).Save(outputPath = Path.Combine(directory,
                                                                                            AssetUtil.CrcFullName(fileName, "models") + ".ean"));
                        list.Add(new FileEntry(outputPath, "animation.ean"));
                        break;

                    case "material":
                    {
                        string name;
                        Helper.AnalyzeFileName(out name, out outputPath, fileName);
                        var ema = AssetHelper.ParseEma(root, name);
                        ema.Save(Path.Combine(directory, outputPath += ".ema"));
                        list.Add(new FileEntry(outputPath, "material.ema"));
                        break;
                    }

                    case "models":
                    {
                        string name;
                        Helper.AnalyzeFileName(out name, out outputPath, fileName);
                        var eso = AssetHelper.ParseEso(root, name);
                        eso.Save(Path.Combine(directory, outputPath += ".eso"));
                        list.Add(new FileEntry(outputPath, "model.eso"));
                        break;
                    }

                    case "font":
                    {
                        CompileFont(inputPath, out outputPath, root);
                        list.Add(new FileEntry(outputPath, "font.bin"));
                        break;
                    }
                    }
                    break;

                case ".loc":
                    LOC.FromFile(file).SaveXls(outputPath += ".xls");
                    list.Add(new FileEntry(outputPath, "text.xls"));
                    break;

                case ".xls":
                    LocHelper.FromXls(file).Save(outputPath += ".loc");
                    list.Add(new FileEntry(outputPath, "text.loc"));
                    break;

                case ".etx":
                    var etx = ETX.FromFile(file);
                    etx.GetBitmap().Save(outputPath = Path.Combine(directory, etx.AssetHeader.Name + ".png"));
                    list.Add(new FileEntry(outputPath, "texture.png"));
                    break;

                case ".png":
                {
                    var name = AssetUtil.CrcFullName(fileName, "textures") + ".etx";
                    (exFormat ? (ETX)ETX1804.CreateFromImage(file) : ETX1803.CreateFromImage(file))
                    .Save(outputPath = Path.Combine(directory, name));
                    list.Add(new FileEntry(outputPath, "texture.etx"));
                    break;
                }

                case ".ean":
                    var ean = EAN.FromFile(file);
                    File.WriteAllText(outputPath = Path.Combine(directory,
                                                                Helper.GetDecompiledFileName(fileName, ean) + ".xml"),
                                      AssetHelper.GetEanElement(ean).ToString());
                    list.Add(new FileEntry(outputPath, "animation.xml"));
                    break;

                case ".ema":
                {
                    var ema = EMA.FromFile(file);
                    File.WriteAllText(outputPath = Path.Combine(directory,
                                                                Helper.GetDecompiledFileName(fileName, ema) + ".xml"),
                                      AssetHelper.GetEmaElement(ema).ToString());
                    list.Add(new FileEntry(outputPath, "material.xml"));
                    break;
                }

                case ".eso":
                {
                    var eso = ESO.FromFile(file);
                    File.WriteAllText(outputPath = Path.Combine(directory,
                                                                Helper.GetDecompiledFileName(fileName, eso) + ".xml"),
                                      AssetHelper.GetEsoElement(eso).ToString());
                    list.Add(new FileEntry(outputPath, "model.xml"));
                    break;
                }

                case ".txt":
                    using (var stream = new FileStream(outputPath += ".bin", FileMode.Create,
                                                       FileAccess.Write, FileShare.Read))
                    {
                        var writer = new BinaryWriter(stream);
                        foreach (var num in File.ReadAllText(file)
                                 .Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)
                                 .Select(double.Parse))
                        {
                            writer.Write((short)Math.Round(num * 256));
                        }
                    }
                    list.Add(new FileEntry(outputPath, "cos.bin"));
                    break;

                default:
                    switch (Path.GetFileName(file))
                    {
                    case "audio":
                        if (Directory.Exists(outputPath = Path.Combine(directory, "sfx")))
                        {
                            Directory.Delete(outputPath, true);
                        }
                        Directory.CreateDirectory(outputPath);
                        string xsb = Path.Combine(file, "sfx.xsb"), xwb = Path.Combine(file, "sfx.xwb");
                        int    offset;
                        using (var stream = new FileStream(xsb, FileMode.Open))
                        {
                            stream.Position = 0x2A;
                            using (var reader = new BinaryReader(stream)) offset = reader.ReadInt32();
                        }
                        var unxwb = new Process {
                            StartInfo = new ProcessStartInfo(
                                Path.Combine(CurrentApp.Directory, "Resources/Libraries/unxwb.exe"),
                                FormattableString.Invariant($"-d \"{outputPath}\" -b \"{xsb}\" {offset} \"{xwb}\""))
                            {
                                UseShellExecute = false, CreateNoWindow = true
                            }
                        };
                        unxwb.Start();
                        unxwb.WaitForExit();
                        list.Add(new FileEntry(outputPath, "sfx"));
                        break;

                    case "sfx":
                        Directory.CreateDirectory(outputPath = Path.Combine(directory, "audio"));
                        string tempPath       = Helper.GetRandomDirectory(),
                               tempInputPath  = Path.Combine(tempPath, "sfx"),
                               tempOutputPath = Path.Combine(tempPath, "audio");

                        /************************************************************************************
                        *     create temp input dir because it's still occupied for unknown reason;        *
                        *     create temp output dir because COMException will be thrown if output dir and *
                        * temp input dir is not under the same drive.                                      *
                        ************************************************************************************/
                        Directory.CreateDirectory(tempInputPath);
                        var projectPath = GenerateXactProject(file, tempInputPath);
                        using (var project = new CXACTMasterProject())
                        {
                            project.Create();
                            project.Load(projectPath, new CXACTMasterProjectCallback(), 0);
                            project.Build(new CXACTMasterProjectCallback(), tempOutputPath, false, false);
                        }
                        foreach (var path in Directory.EnumerateFiles(tempOutputPath))
                        {
                            var target = Path.Combine(outputPath, Path.GetFileName(path));
                            File.Delete(target);
                            File.Move(path, target);
                        }
                        try
                        {
                            Directory.Delete(tempPath, true);
                        }
                        catch
                        {
                            Trace.WriteLine(tempPath, "Delete tempPath failed");
                        }
                        list.Add(new FileEntry(outputPath, "audio"));
                        break;

                    default:
                        throw new NotSupportedException(Localization.DecompileUnrecognizedFile);
                    }
                    break;
                }
                return(new Tuple <Exception, string, List <FileEntry> >(null, Warning.Fetch(), list));
            }
            catch (Exception exc)
            {
                return(new Tuple <Exception, string, List <FileEntry> >(exc, Warning.Fetch(), list));
            }
            finally
            {
                Warning.Clear();
            }
        }