예제 #1
0
파일: ZipFile.cs 프로젝트: pchote/OpenRA
        public ZipFile(Stream stream, string name, IReadOnlyPackage parent = null)
        {
            // SharpZipLib breaks when asked to update archives loaded from outside streams or files
            // We can work around this by creating a clean in-memory-only file, cutting all outside references
            pkgStream = new MemoryStream();
            stream.CopyTo(pkgStream);
            pkgStream.Position = 0;

            Name = name;
            Parent = parent as IReadWritePackage;
            pkg = new SZipFile(pkgStream);
        }
예제 #2
0
        public void LoadMaps()
        {
            // Utility mod that does not support maps
            if (!modData.Manifest.Contains <MapGrid>())
            {
                return;
            }

            var mapGrid = modData.Manifest.Get <MapGrid>();

            foreach (var kv in MapLocations)
            {
                foreach (var map in kv.Key.Contents)
                {
                    IReadOnlyPackage mapPackage = null;
                    try
                    {
                        using (new Support.PerfTimer(map))
                        {
                            mapPackage = modData.ModFiles.OpenPackage(map, kv.Key);
                            if (mapPackage == null)
                            {
                                continue;
                            }

                            var uid = Map.ComputeUID(mapPackage);
                            previews[uid].UpdateFromMap(mapPackage, kv.Key, kv.Value, modData.Manifest.MapCompatibility, mapGrid.Type);
                        }
                    }
                    catch (Exception e)
                    {
                        if (mapPackage != null)
                        {
                            mapPackage.Dispose();
                        }
                        Console.WriteLine("Failed to load map: {0}", map);
                        Console.WriteLine("Details: {0}", e);
                        Log.Write("debug", "Failed to load map: {0}", map);
                        Log.Write("debug", "Details: {0}", e);
                    }
                }
            }
        }
예제 #3
0
        public bool Unmount(IReadOnlyPackage package)
        {
            var mountCount = 0;

            if (!mountedPackages.TryGetValue(package, out mountCount))
            {
                return(false);
            }

            if (--mountCount <= 0)
            {
                foreach (var packagesForFile in fileIndex.Values)
                {
                    packagesForFile.RemoveAll(p => p == package);
                }

                mountedPackages.Remove(package);
                var explicitKeys = explicitMounts.Where(kv => kv.Value == package)
                                   .Select(kv => kv.Key)
                                   .ToList();

                foreach (var key in explicitKeys)
                {
                    explicitMounts.Remove(key);
                }

                // Mod packages aren't owned by us, so we shouldn't dispose them
                if (modPackages.Contains(package))
                {
                    modPackages.Remove(package);
                }
                else
                {
                    package.Dispose();
                }
            }
            else
            {
                mountedPackages[package] = mountCount;
            }

            return(true);
        }
예제 #4
0
        static Manifest LoadMod(string id, string path)
        {
            IReadOnlyPackage package = null;

            try
            {
                if (Directory.Exists(path))
                {
                    package = new Folder(path);
                }
                else
                {
                    try
                    {
                        using (var fileStream = File.OpenRead(path))
                            package = new ZipFile(fileStream, path);
                    }
                    catch
                    {
                        throw new InvalidDataException(path + " is not a valid mod package");
                    }
                }

                if (!package.Contains("mod.yaml"))
                {
                    throw new InvalidDataException(path + " is not a valid mod package");
                }

                // Mods in the support directory and oramod packages (which are listed later
                // in the CandidateMods list) override mods in the main install.
                return(new Manifest(id, package));
            }
            catch (Exception)
            {
                if (package != null)
                {
                    package.Dispose();
                }

                return(null);
            }
        }
예제 #5
0
        bool IPackageLoader.TryParsePackage(Stream s, string filename, FS context, out IReadOnlyPackage package)
        {
            if (!filename.EndsWith(".mix", StringComparison.InvariantCultureIgnoreCase))
            {
                package = null;
                return(false);
            }

            // Load the global mix database
            if (globalFilenames == null)
            {
                if (context.TryOpen("global mix database.dat", out var mixDatabase))
                {
                    using (var db = new XccGlobalDatabase(mixDatabase))
                        globalFilenames = db.Entries.Distinct().ToArray();
                }
            }

            package = new MixFile(s, filename, globalFilenames ?? Array.Empty <string>());
            return(true);
        }
예제 #6
0
        public bool TryParsePackage(Stream s, string filename, FS context, out IReadOnlyPackage package)
        {
            if (filename.EndsWith(".lpk") ||          // Spritesheet container
                filename.EndsWith(".bpk") ||             // Image container
                filename.EndsWith(".spk") ||             // Sound set
                filename.EndsWith(".lps") ||             // Singleplayer map
                filename.EndsWith(".lpm") ||             // Multiplayer map
                filename.EndsWith(".mpk"))                // Matrix set (destroyable map part, tile replacements)
            {
                s = Crypter.Decrypt(s);
            }

            var signature = s.ReadASCII(4);

            var version = Version.UNKNOWN;

            if (signature.Equals("DATA"))
            {
                version = Version.KKND1;
            }

            if (signature.Equals("DAT2"))
            {
                version = Version.KKND2;
            }

            if (version == Version.UNKNOWN)
            {
                s.Position -= 4;
                package     = null;
                return(false);
            }

            var tmp        = s.ReadBytes(4);      // Big-Endian
            var dataLength = (tmp[0] << 24) | (tmp[1] << 16) | (tmp[2] << 8) | tmp[3];

            package = new LvlPackage(new SegmentStream(s, 8, dataLength), filename, context);

            return(true);
        }
예제 #7
0
파일: MixFile.cs 프로젝트: dnqbob/OpenRA
        bool IPackageLoader.TryParsePackage(Stream s, string filename, FS context, out IReadOnlyPackage package)
        {
            if (!filename.EndsWith(".mix", StringComparison.InvariantCultureIgnoreCase))
            {
                package = null;
                return(false);
            }

            // Load the global mix database
            var allPossibleFilenames = new HashSet <string>();

            if (context.TryOpen("global mix database.dat", out var mixDatabase))
            {
                using (var db = new XccGlobalDatabase(mixDatabase))
                    foreach (var e in db.Entries)
                    {
                        allPossibleFilenames.Add(e);
                    }
            }

            package = new MixFile(s, filename, allPossibleFilenames);
            return(true);
        }
예제 #8
0
        string GetSourceDisplayName(IReadOnlyPackage source)
        {
            if (source == null)
            {
                return("All Packages");
            }

            // Packages that are explicitly mounted in the filesystem use their explicit mount name
            var fs   = (OpenRA.FileSystem.FileSystem)modData.DefaultFileSystem;
            var name = fs.GetPrefix(source);

            // Fall back to the path relative to the mod, engine, or support dir
            if (name == null)
            {
                name = source.Name;
                var compare = Platform.CurrentPlatform == PlatformType.Windows ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal;
                if (name.StartsWith(modData.Manifest.Package.Name, compare))
                {
                    name = "$" + modData.Manifest.Id + "/" + name.Substring(modData.Manifest.Package.Name.Length + 1);
                }
                else if (name.StartsWith(Platform.EngineDir, compare))
                {
                    name = "./" + name.Substring(Platform.EngineDir.Length);
                }
                else if (name.StartsWith(Platform.SupportDir, compare))
                {
                    name = "^" + name.Substring(Platform.SupportDir.Length);
                }
            }

            if (name.Length > 18)
            {
                name = "..." + name.Substring(name.Length - 15);
            }

            return(name);
        }
예제 #9
0
        Manifest LoadMod(string id, string path)
        {
            IReadOnlyPackage package = null;

            try
            {
                if (!Directory.Exists(path))
                {
                    throw new InvalidDataException(path + " is not a valid mod package");
                }

                package = new Folder(path);
                if (!package.Contains("mod.yaml"))
                {
                    throw new InvalidDataException(path + " is not a valid mod package");
                }

                using (var stream = package.GetStream("icon.png"))
                    if (stream != null)
                    {
                        using (var bitmap = new Bitmap(stream))
                            icons[id] = sheetBuilder.Add(bitmap);
                    }

                return(new Manifest(id, package));
            }
            catch (Exception)
            {
                if (package != null)
                {
                    package.Dispose();
                }

                return(null);
            }
        }
예제 #10
0
        public Manifest(string modId, IReadOnlyPackage package)
        {
            Id      = modId;
            Package = package;
            yaml    = new MiniYaml(null, MiniYaml.FromStream(package.GetStream("mod.yaml"), "mod.yaml")).ToDictionary();

            Metadata = FieldLoader.Load <ModMetadata>(yaml["Metadata"]);

            // TODO: Use fieldloader
            MapFolders = YamlDictionary(yaml, "MapFolders");

            MiniYaml packages;

            if (yaml.TryGetValue("Packages", out packages))
            {
                Packages = packages.ToDictionary(x => x.Value).AsReadOnly();
            }

            Rules          = YamlList(yaml, "Rules");
            Sequences      = YamlList(yaml, "Sequences");
            ModelSequences = YamlList(yaml, "ModelSequences");
            Cursors        = YamlList(yaml, "Cursors");
            Chrome         = YamlList(yaml, "Chrome");
            Assemblies     = YamlList(yaml, "Assemblies");
            ChromeLayout   = YamlList(yaml, "ChromeLayout");
            Weapons        = YamlList(yaml, "Weapons");
            Voices         = YamlList(yaml, "Voices");
            Notifications  = YamlList(yaml, "Notifications");
            Music          = YamlList(yaml, "Music");
            Translations   = YamlList(yaml, "Translations");
            TileSets       = YamlList(yaml, "TileSets");
            ChromeMetrics  = YamlList(yaml, "ChromeMetrics");
            Missions       = YamlList(yaml, "Missions");
            Hotkeys        = YamlList(yaml, "Hotkeys");

            ServerTraits = YamlList(yaml, "ServerTraits");

            if (!yaml.TryGetValue("LoadScreen", out LoadScreen))
            {
                throw new InvalidDataException("`LoadScreen` section is not defined.");
            }

            // Allow inherited mods to import parent maps.
            var compat = new List <string> {
                Id
            };

            if (yaml.ContainsKey("SupportsMapsFrom"))
            {
                compat.AddRange(yaml["SupportsMapsFrom"].Value.Split(',').Select(c => c.Trim()));
            }

            MapCompatibility = compat.ToArray();

            if (yaml.ContainsKey("PackageFormats"))
            {
                PackageFormats = FieldLoader.GetValue <string[]>("PackageFormats", yaml["PackageFormats"].Value);
            }

            if (yaml.ContainsKey("SoundFormats"))
            {
                SoundFormats = FieldLoader.GetValue <string[]>("SoundFormats", yaml["SoundFormats"].Value);
            }

            if (yaml.ContainsKey("SpriteFormats"))
            {
                SpriteFormats = FieldLoader.GetValue <string[]>("SpriteFormats", yaml["SpriteFormats"].Value);
            }
        }
예제 #11
0
        public bool TryParsePackage(Stream s, string filename, OpenRA.FileSystem.FileSystem context, out IReadOnlyPackage package)
        {
            var position = s.Position;

            var id      = s.ReadUInt32();
            var version = s.ReadUInt32();

            s.Position = position;

            if (id != UnencryptedMegID || version != MegVersion)
            {
                package = null;
                return(false);
            }

            package = new MegFile(s, filename);
            return(true);
        }
예제 #12
0
        bool IPackageLoader.TryParsePackage(Stream s, string filename, FileSystem.FileSystem context, out IReadOnlyPackage package)
        {
            if (!filename.EndsWith(".rs", StringComparison.InvariantCultureIgnoreCase))
            {
                package = null;
                return(false);
            }

            package = new D2kSoundResources(s, filename);
            return(true);
        }
예제 #13
0
파일: MapCache.cs 프로젝트: hadow/Commander
        /// <summary>
        /// ╪сть╣ьм╪
        /// </summary>
        public void LoadMaps()
        {
            if (!this.modData.Manifest.Contains <MapGrid>())
            {
                return;
            }

            //Enumerate map directories
            foreach (var kv in modData.Manifest.MapFolders)
            {
                var name           = kv.Key;
                var classification = string.IsNullOrEmpty(kv.Value) ? MapClassification.Unknown :
                                     Enum <MapClassification> .Parse(kv.Value);

                IReadOnlyPackage package;
                var optional = name.StartsWith("~", StringComparison.Ordinal);
                if (optional)
                {
                    name = name.Substring(1);
                }

                try
                {
                    package = modData.ModFiles.OpenPackage(name);
                }
                catch
                {
                    if (optional)
                    {
                        continue;
                    }
                    throw;
                }
                mapLocations.Add(package, classification);
            }
            var mapGrid = this.modData.Manifest.Get <MapGrid>();

            foreach (var kv in MapLocations)
            {
                foreach (var map in kv.Key.Contents)
                {
                    IReadOnlyPackage mapPackage = null;
                    try
                    {
                        using (new Support.PerfTimer(map))
                        {
                            mapPackage = kv.Key.OpenPackage(map, modData.ModFiles);
                            if (mapPackage == null)
                            {
                                continue;
                            }

                            var uid = Map.ComputeUID(mapPackage);
                            previews[uid].UpdateFromMap(mapPackage, kv.Key, kv.Value, modData.Manifest.MapCompatibility, mapGrid.Type);
                        }
                    }
                    catch (Exception e)
                    {
                        if (mapPackage != null)
                        {
                            mapPackage.Dispose();
                        }
                    }
                }
            }
        }
예제 #14
0
        bool ShowSourceDropdown(DropDownButtonWidget dropdown)
        {
            Func<IReadOnlyPackage, ScrollItemWidget, ScrollItemWidget> setupItem = (source, itemTemplate) =>
            {
                var item = ScrollItemWidget.Setup(itemTemplate,
                    () => assetSource == source,
                    () => { assetSource = source; PopulateAssetList(); });
                item.Get<LabelWidget>("LABEL").GetText = () => source != null ? Platform.UnresolvePath(source.Name) : "All Packages";
                return item;
            };

            var sources = new[] { (IReadOnlyPackage)null }.Concat(acceptablePackages);
            dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 280, sources, setupItem);
            return true;
        }
예제 #15
0
        public void UpdateFromMap(IReadOnlyPackage p, IReadOnlyPackage parent, MapClassification classification, string[] mapCompatibility, MapGridType gridType)
        {
            Dictionary <string, MiniYaml> yaml;

            using (var yamlStream = p.GetStream("map.yaml"))
            {
                if (yamlStream == null)
                {
                    throw new FileNotFoundException("Required file map.yaml not present in this map");
                }

                yaml = new MiniYaml(null, MiniYaml.FromStream(yamlStream, "map.yaml")).ToDictionary();
            }

            Package       = p;
            parentPackage = parent;

            var newData = innerData.Clone();

            newData.GridType = gridType;
            newData.Class    = classification;

            MiniYaml temp;

            if (yaml.TryGetValue("MapFormat", out temp))
            {
                var format = FieldLoader.GetValue <int>("MapFormat", temp.Value);
                if (format != Map.SupportedMapFormat)
                {
                    throw new InvalidDataException("Map format {0} is not supported.".F(format));
                }
            }

            if (yaml.TryGetValue("Title", out temp))
            {
                newData.Title = temp.Value;
            }

            if (yaml.TryGetValue("Categories", out temp))
            {
                newData.Categories = FieldLoader.GetValue <string[]>("Categories", temp.Value);
            }

            if (yaml.TryGetValue("Tileset", out temp))
            {
                newData.TileSet = temp.Value;
            }

            if (yaml.TryGetValue("Author", out temp))
            {
                newData.Author = temp.Value;
            }

            if (yaml.TryGetValue("Bounds", out temp))
            {
                newData.Bounds = FieldLoader.GetValue <Rectangle>("Bounds", temp.Value);
            }

            if (yaml.TryGetValue("Visibility", out temp))
            {
                newData.Visibility = FieldLoader.GetValue <MapVisibility>("Visibility", temp.Value);
            }

            string requiresMod = string.Empty;

            if (yaml.TryGetValue("RequiresMod", out temp))
            {
                requiresMod = temp.Value;
            }

            newData.Status = mapCompatibility == null || mapCompatibility.Contains(requiresMod) ?
                             MapStatus.Available : MapStatus.Unavailable;

            try
            {
                // Actor definitions may change if the map format changes
                MiniYaml actorDefinitions;
                if (yaml.TryGetValue("Actors", out actorDefinitions))
                {
                    var spawns = new List <CPos>();
                    foreach (var kv in actorDefinitions.Nodes.Where(d => d.Value.Value == "mpspawn"))
                    {
                        var s = new ActorReference(kv.Value.Value, kv.Value.ToDictionary());
                        spawns.Add(s.InitDict.Get <LocationInit>().Value(null));
                    }

                    newData.SpawnPoints = spawns.ToArray();
                }
                else
                {
                    newData.SpawnPoints = new CPos[0];
                }
            }
            catch (Exception)
            {
                newData.SpawnPoints = new CPos[0];
                newData.Status      = MapStatus.Unavailable;
            }

            try
            {
                // Player definitions may change if the map format changes
                MiniYaml playerDefinitions;
                if (yaml.TryGetValue("Players", out playerDefinitions))
                {
                    newData.Players     = new MapPlayers(playerDefinitions.Nodes);
                    newData.PlayerCount = newData.Players.Players.Count(x => x.Value.Playable);
                }
            }
            catch (Exception)
            {
                newData.Status = MapStatus.Unavailable;
            }

            newData.SetRulesetGenerator(modData, () =>
            {
                var ruleDefinitions          = LoadRuleSection(yaml, "Rules");
                var weaponDefinitions        = LoadRuleSection(yaml, "Weapons");
                var voiceDefinitions         = LoadRuleSection(yaml, "Voices");
                var musicDefinitions         = LoadRuleSection(yaml, "Music");
                var notificationDefinitions  = LoadRuleSection(yaml, "Notifications");
                var sequenceDefinitions      = LoadRuleSection(yaml, "Sequences");
                var modelSequenceDefinitions = LoadRuleSection(yaml, "ModelSequences");
                var rules = Ruleset.Load(modData, this, TileSet, ruleDefinitions, weaponDefinitions,
                                         voiceDefinitions, notificationDefinitions, musicDefinitions, sequenceDefinitions, modelSequenceDefinitions);
                var flagged = Ruleset.DefinesUnsafeCustomRules(modData, this, ruleDefinitions,
                                                               weaponDefinitions, voiceDefinitions, notificationDefinitions, sequenceDefinitions);
                return(Pair.New(rules, flagged));
            });

            if (p.Contains("map.png"))
            {
                using (var dataStream = p.GetStream("map.png"))
                    newData.Preview = new Bitmap(dataStream);
            }

            // Assign the new data atomically
            innerData = newData;
        }
예제 #16
0
파일: Manifest.cs 프로젝트: hadow/Commander
        public Manifest(string modId, IReadOnlyPackage package)
        {
            Id      = modId;
            Package = package;

            yaml = new MiniYaml(null, MiniYaml.FromStream(Package.GetStream("mod.yaml"), "mod.yaml")).ToDictionary();

            Metadata = FieldLoader.Load <ModMetadata>(yaml["Metadata"]);

            MapFolders = YamlDictionary(yaml, "MapFolders");

            MiniYaml packages;

            if (yaml.TryGetValue("Packages", out packages))
            {
                Packages = packages.ToDictionary(x => x.Value).AsReadOnly();
            }
            Rules          = YamlList(yaml, "Rules");
            Sequences      = YamlList(yaml, "Sequences");
            ModelSequences = YamlList(yaml, "ModelSequences");
            Assemblies     = YamlList(yaml, "Assemblies");
            Weapons        = YamlList(yaml, "Weapons");
            Voices         = YamlList(yaml, "Voices");
            Notifications  = YamlList(yaml, "Notifications");
            Music          = YamlList(yaml, "Music");
            TileSets       = YamlList(yaml, "TileSets");
            Missions       = YamlList(yaml, "Missions");
            ServerTraits   = YamlList(yaml, "ServerTraits");
            Chrome         = YamlList(yaml, "Chrome");
            ChromeLayout   = YamlList(yaml, "ChromeLayout");
            ChromeMetrics  = YamlList(yaml, "ChromeMetrics");
            Fonts          = yaml["Fonts"].ToDictionary(my =>
            {
                var nd = my.ToDictionary();
                return(Pair.New(nd["Font"].Value, Exts.ParseIntegerInvariant(nd["Size"].Value)));
            });
            if (!yaml.TryGetValue("LoadScreen", out LoadScreen))
            {
                throw new InvalidDataException("'LoadScreen' section is not defined.");
            }

            var compat = new List <string> {
                Id
            };

            if (yaml.ContainsKey("SupportsMapsFrom"))
            {
                compat.AddRange(yaml["SupportsMapsFrom"].Value.Split(',').Select(c => c.Trim()));
            }

            MapCompatibility = compat.ToArray();

            if (yaml.ContainsKey("SpriteFormats"))
            {
                SpriteFormats = FieldLoader.GetValue <string[]>("SpriteFormats", yaml["SpriteFormats"].Value);
            }

            if (yaml.ContainsKey("PackageFormats"))
            {
                PackageFormats = FieldLoader.GetValue <string[]>("PackageFormats", yaml["PackageFormats"].Value);
            }

            if (yaml.ContainsKey("SoundFormats"))
            {
                SoundFormats = FieldLoader.GetValue <string[]>("SoundFormats", yaml["SoundFormats"].Value);
            }
        }
예제 #17
0
        static Dictionary <string, ModMetadata> ValidateMods()
        {
            var ret = new Dictionary <string, ModMetadata>();

            foreach (var pair in GetCandidateMods())
            {
                IReadOnlyPackage package = null;
                try
                {
                    if (Directory.Exists(pair.Second))
                    {
                        package = new Folder(pair.Second);
                    }
                    else
                    {
                        try
                        {
                            package = new ZipFile(null, pair.Second);
                        }
                        catch
                        {
                            throw new InvalidDataException(pair.Second + " is not a valid mod package");
                        }
                    }

                    if (!package.Contains("mod.yaml"))
                    {
                        package.Dispose();
                        continue;
                    }

                    var yaml = new MiniYaml(null, MiniYaml.FromStream(package.GetStream("mod.yaml")));
                    var nd   = yaml.ToDictionary();
                    if (!nd.ContainsKey("Metadata"))
                    {
                        package.Dispose();
                        continue;
                    }

                    var metadata = FieldLoader.Load <ModMetadata>(nd["Metadata"]);
                    metadata.Id      = pair.First;
                    metadata.Package = package;

                    if (nd.ContainsKey("RequiresMods"))
                    {
                        metadata.RequiresMods = nd["RequiresMods"].ToDictionary(my => my.Value);
                    }
                    else
                    {
                        metadata.RequiresMods = new Dictionary <string, string>();
                    }

                    if (nd.ContainsKey("ContentInstaller"))
                    {
                        metadata.Content = FieldLoader.Load <ContentInstaller>(nd["ContentInstaller"]);
                    }

                    // Mods in the support directory and oramod packages (which are listed later
                    // in the CandidateMods list) override mods in the main install.
                    ret[pair.First] = metadata;
                }
                catch (Exception ex)
                {
                    if (package != null)
                    {
                        package.Dispose();
                    }
                    Console.WriteLine("An exception occurred when trying to load ModMetadata for `{0}`:".F(pair.First));
                    Console.WriteLine(ex.Message);
                }
            }

            return(ret);
        }
예제 #18
0
파일: MapPreview.cs 프로젝트: pchote/OpenRA
 bool IReadOnlyFileSystem.TryGetPackageContaining(string path, out IReadOnlyPackage package, out string filename)
 {
     // Packages aren't supported inside maps
     return modData.DefaultFileSystem.TryGetPackageContaining(path, out package, out filename);
 }
예제 #19
0
        bool LoadAsset(IReadOnlyPackage package, string filename)
        {
            ClearLoadedAssets();

            if (string.IsNullOrEmpty(filename))
            {
                return(false);
            }

            if (!package.Contains(filename))
            {
                return(false);
            }

            isLoadError = false;

            try
            {
                currentPackage  = package;
                currentFilename = filename;
                var prefix = "";

                if (modData.DefaultFileSystem is OpenRA.FileSystem.FileSystem fs)
                {
                    prefix = fs.GetPrefix(package);
                    if (prefix != null)
                    {
                        prefix += "|";
                    }
                }

                var fileExtension = Path.GetExtension(filename.ToLowerInvariant());
                if (allowedSpriteExtensions.Contains(fileExtension))
                {
                    currentSprites = world.Map.Rules.Sequences.SpriteCache[prefix + filename];
                    currentFrame   = 0;

                    if (frameSlider != null)
                    {
                        frameSlider.MaximumValue = (float)currentSprites.Length - 1;
                        frameSlider.Ticks        = currentSprites.Length;
                    }

                    currentVoxel = null;
                }
                else if (allowedModelExtensions.Contains(fileExtension))
                {
                    var voxelName = Path.GetFileNameWithoutExtension(filename);
                    currentVoxel   = world.ModelCache.GetModel(voxelName);
                    currentSprites = null;
                }
                else if (allowedAudioExtensions.Contains(fileExtension))
                {
                    // Mute music so it doesn't interfere with the current asset.
                    MuteSounds();

                    currentAudioStream = Game.ModData.DefaultFileSystem.Open(prefix + filename);
                    foreach (var modDataSoundLoader in Game.ModData.SoundLoaders)
                    {
                        if (modDataSoundLoader.TryParseSound(currentAudioStream, out currentSoundFormat))
                        {
                            if (frameSlider != null)
                            {
                                frameSlider.MaximumValue = currentSoundFormat.LengthInSeconds * currentSoundFormat.SampleRate;
                                frameSlider.Ticks        = 0;
                            }

                            break;
                        }
                    }
                }
                else if (allowedVideoExtensions.Contains(fileExtension))
                {
                    // Mute music so it doesn't interfere with the current asset.
                    MuteSounds();

                    var video = VideoLoader.GetVideo(Game.ModData.DefaultFileSystem.Open(filename), true, Game.ModData.VideoLoaders);
                    if (video != null)
                    {
                        player = panel.Get <VideoPlayerWidget>("PLAYER");
                        player.Load(prefix + filename);
                        player.DrawOverlay = false;
                        isVideoLoaded      = true;

                        if (frameSlider != null)
                        {
                            frameSlider.MaximumValue = (float)player.Video.FrameCount - 1;
                            frameSlider.Ticks        = 0;
                        }
                    }
                }
                else
                {
                    return(false);
                }
            }
            catch (Exception ex)
            {
                isLoadError = true;
                Log.AddChannel("assetbrowser", "assetbrowser.log");
                Log.Write("assetbrowser", "Error reading {0}:{3} {1}{3}{2}", filename, ex.Message, ex.StackTrace, Environment.NewLine);

                return(false);
            }

            return(true);
        }
예제 #20
0
파일: MapPreview.cs 프로젝트: pchote/OpenRA
        public void UpdateFromMap(IReadOnlyPackage p, IReadOnlyPackage parent, MapClassification classification, string[] mapCompatibility, MapGridType gridType)
        {
            Dictionary<string, MiniYaml> yaml;
            using (var yamlStream = p.GetStream("map.yaml"))
            {
                if (yamlStream == null)
                    throw new FileNotFoundException("Required file map.yaml not present in this map");

                yaml = new MiniYaml(null, MiniYaml.FromStream(yamlStream, "map.yaml")).ToDictionary();
            }

            Package = p;
            parentPackage = parent;

            var newData = innerData.Clone();
            newData.GridType = gridType;
            newData.Class = classification;

            MiniYaml temp;
            if (yaml.TryGetValue("MapFormat", out temp))
            {
                var format = FieldLoader.GetValue<int>("MapFormat", temp.Value);
                if (format != Map.SupportedMapFormat)
                    throw new InvalidDataException("Map format {0} is not supported.".F(format));
            }

            if (yaml.TryGetValue("Title", out temp))
                newData.Title = temp.Value;

            if (yaml.TryGetValue("Categories", out temp))
                newData.Categories = FieldLoader.GetValue<string[]>("Categories", temp.Value);

            if (yaml.TryGetValue("Tileset", out temp))
                newData.TileSet = temp.Value;

            if (yaml.TryGetValue("Author", out temp))
                newData.Author = temp.Value;

            if (yaml.TryGetValue("Bounds", out temp))
                newData.Bounds = FieldLoader.GetValue<Rectangle>("Bounds", temp.Value);

            if (yaml.TryGetValue("Visibility", out temp))
                newData.Visibility = FieldLoader.GetValue<MapVisibility>("Visibility", temp.Value);

            string requiresMod = string.Empty;
            if (yaml.TryGetValue("RequiresMod", out temp))
                requiresMod = temp.Value;

            newData.Status = mapCompatibility == null || mapCompatibility.Contains(requiresMod) ?
                MapStatus.Available : MapStatus.Unavailable;

            try
            {
                // Actor definitions may change if the map format changes
                MiniYaml actorDefinitions;
                if (yaml.TryGetValue("Actors", out actorDefinitions))
                {
                    var spawns = new List<CPos>();
                    foreach (var kv in actorDefinitions.Nodes.Where(d => d.Value.Value == "mpspawn"))
                    {
                        var s = new ActorReference(kv.Value.Value, kv.Value.ToDictionary());
                        spawns.Add(s.InitDict.Get<LocationInit>().Value(null));
                    }

                    newData.SpawnPoints = spawns.ToArray();
                }
                else
                    newData.SpawnPoints = new CPos[0];
            }
            catch (Exception)
            {
                newData.SpawnPoints = new CPos[0];
                newData.Status = MapStatus.Unavailable;
            }

            try
            {
                // Player definitions may change if the map format changes
                MiniYaml playerDefinitions;
                if (yaml.TryGetValue("Players", out playerDefinitions))
                {
                    newData.Players = new MapPlayers(playerDefinitions.Nodes);
                    newData.PlayerCount = newData.Players.Players.Count(x => x.Value.Playable);
                }
            }
            catch (Exception)
            {
                newData.Status = MapStatus.Unavailable;
            }

            newData.SetRulesetGenerator(modData, () =>
            {
                var ruleDefinitions = LoadRuleSection(yaml, "Rules");
                var weaponDefinitions = LoadRuleSection(yaml, "Weapons");
                var voiceDefinitions = LoadRuleSection(yaml, "Voices");
                var musicDefinitions = LoadRuleSection(yaml, "Music");
                var notificationDefinitions = LoadRuleSection(yaml, "Notifications");
                var sequenceDefinitions = LoadRuleSection(yaml, "Sequences");
                var rules = Ruleset.Load(modData, this, TileSet, ruleDefinitions, weaponDefinitions,
                    voiceDefinitions, notificationDefinitions, musicDefinitions, sequenceDefinitions);
                var flagged = Ruleset.DefinesUnsafeCustomRules(modData, this, ruleDefinitions,
                    weaponDefinitions, voiceDefinitions, notificationDefinitions, sequenceDefinitions);
                return Pair.New(rules, flagged);
            });

            if (p.Contains("map.png"))
                using (var dataStream = p.GetStream("map.png"))
                    newData.Preview = new Bitmap(dataStream);

            // Assign the new data atomically
            innerData = newData;
        }
예제 #21
0
파일: Map.cs 프로젝트: pchote/OpenRA
        public Map(ModData modData, IReadOnlyPackage package)
        {
            this.modData = modData;
            Package = package;

            if (!Package.Contains("map.yaml") || !Package.Contains("map.bin"))
                throw new InvalidDataException("Not a valid map\n File: {0}".F(package.Name));

            var yaml = new MiniYaml(null, MiniYaml.FromStream(Package.GetStream("map.yaml"), package.Name));
            foreach (var field in YamlFields)
                field.Deserialize(this, yaml.Nodes);

            if (MapFormat != SupportedMapFormat)
                throw new InvalidDataException("Map format {0} is not supported.\n File: {1}".F(MapFormat, package.Name));

            PlayerDefinitions = MiniYaml.NodesOrEmpty(yaml, "Players");
            ActorDefinitions = MiniYaml.NodesOrEmpty(yaml, "Actors");

            Grid = modData.Manifest.Get<MapGrid>();

            var size = new Size(MapSize.X, MapSize.Y);
            Tiles = new CellLayer<TerrainTile>(Grid.Type, size);
            Resources = new CellLayer<ResourceTile>(Grid.Type, size);
            Height = new CellLayer<byte>(Grid.Type, size);

            using (var s = Package.GetStream("map.bin"))
            {
                var header = new BinaryDataHeader(s, MapSize);
                if (header.TilesOffset > 0)
                {
                    s.Position = header.TilesOffset;
                    for (var i = 0; i < MapSize.X; i++)
                    {
                        for (var j = 0; j < MapSize.Y; j++)
                        {
                            var tile = s.ReadUInt16();
                            var index = s.ReadUInt8();

                            // TODO: Remember to remove this when rewriting tile variants / PickAny
                            if (index == byte.MaxValue)
                                index = (byte)(i % 4 + (j % 4) * 4);

                            Tiles[new MPos(i, j)] = new TerrainTile(tile, index);
                        }
                    }
                }

                if (header.ResourcesOffset > 0)
                {
                    s.Position = header.ResourcesOffset;
                    for (var i = 0; i < MapSize.X; i++)
                    {
                        for (var j = 0; j < MapSize.Y; j++)
                        {
                            var type = s.ReadUInt8();
                            var density = s.ReadUInt8();
                            Resources[new MPos(i, j)] = new ResourceTile(type, density);
                        }
                    }
                }

                if (header.HeightsOffset > 0)
                {
                    s.Position = header.HeightsOffset;
                    for (var i = 0; i < MapSize.X; i++)
                        for (var j = 0; j < MapSize.Y; j++)
                            Height[new MPos(i, j)] = s.ReadUInt8().Clamp((byte)0, Grid.MaximumTerrainHeight);
                }
            }

            if (Grid.MaximumTerrainHeight > 0)
            {
                Tiles.CellEntryChanged += UpdateProjection;
                Height.CellEntryChanged += UpdateProjection;
            }

            PostInit();

            Uid = ComputeUID(Package);
        }
예제 #22
0
        bool IPackageLoader.TryParsePackage(Stream s, string filename, FileSystem context, out IReadOnlyPackage package)
        {
            // Take a peek at the file signature
            var signature = s.ReadUInt32();

            s.Position -= 4;

            if (signature != 0x8C655D13)
            {
                package = null;
                return(false);
            }

            package = new InstallShieldPackage(s, filename);
            return(true);
        }
예제 #23
0
파일: Map.cs 프로젝트: pchote/OpenRA
        public static string ComputeUID(IReadOnlyPackage package)
        {
            // UID is calculated by taking an SHA1 of the yaml and binary data
            var requiredFiles = new[] { "map.yaml", "map.bin" };
            var contents = package.Contents.ToList();
            foreach (var required in requiredFiles)
                if (!contents.Contains(required))
                    throw new FileNotFoundException("Required file {0} not present in this map".F(required));

            using (var ms = new MemoryStream())
            {
                foreach (var filename in contents)
                    if (filename.EndsWith(".yaml") || filename.EndsWith(".bin") || filename.EndsWith(".lua"))
                        using (var s = package.GetStream(filename))
                            s.CopyTo(ms);

                // Take the SHA1
                ms.Seek(0, SeekOrigin.Begin);
                return CryptoUtil.SHA1Hash(ms);
            }
        }
예제 #24
0
        public bool TryParsePackage(Stream s, string filename, OpenRA.FileSystem.FileSystem context, out IReadOnlyPackage package)
        {
            if (!filename.EndsWith("DDF"))
            {
                package = null;
                return(false);
            }

            package = new DdfPackage(s, context.Open(filename.Replace(".DDF", ".ANI")), filename);
            return(true);
        }
예제 #25
0
        public void LoadMaps()
        {
            // Utility mod that does not support maps
            if (!modData.Manifest.Contains <MapGrid>())
            {
                return;
            }

            // Enumerate map directories
            foreach (var kv in modData.Manifest.MapFolders)
            {
                var name           = kv.Key;
                var classification = string.IsNullOrEmpty(kv.Value)
                                        ? MapClassification.Unknown : Enum <MapClassification> .Parse(kv.Value);

                IReadOnlyPackage package;
                var optional = name.StartsWith("~", StringComparison.Ordinal);
                if (optional)
                {
                    name = name.Substring(1);
                }

                try
                {
                    // HACK: If the path is inside the the support directory then we may need to create it
                    if (Platform.IsPathRelativeToSupportDirectory(name))
                    {
                        // Assume that the path is a directory if there is not an existing file with the same name
                        var resolved = Platform.ResolvePath(name);
                        if (!File.Exists(resolved))
                        {
                            Directory.CreateDirectory(resolved);
                        }
                    }

                    package = modData.ModFiles.OpenPackage(name);
                }
                catch
                {
                    if (optional)
                    {
                        continue;
                    }

                    throw;
                }

                mapLocations.Add(package, classification);
            }

            var mapGrid = modData.Manifest.Get <MapGrid>();

            foreach (var kv in MapLocations)
            {
                foreach (var map in kv.Key.Contents)
                {
                    IReadOnlyPackage mapPackage = null;
                    try
                    {
                        using (new Support.PerfTimer(map))
                        {
                            mapPackage = kv.Key.OpenPackage(map, modData.ModFiles);
                            if (mapPackage == null)
                            {
                                continue;
                            }

                            var uid = Map.ComputeUID(mapPackage);
                            previews[uid].UpdateFromMap(mapPackage, kv.Key, kv.Value, modData.Manifest.MapCompatibility, mapGrid.Type);
                        }
                    }
                    catch (Exception e)
                    {
                        if (mapPackage != null)
                        {
                            mapPackage.Dispose();
                        }
                        Console.WriteLine("Failed to load map: {0}", map);
                        Console.WriteLine("Details: {0}", e);
                        Log.Write("debug", "Failed to load map: {0}", map);
                        Log.Write("debug", "Details: {0}", e);
                    }
                }
            }
        }
예제 #26
0
파일: Map.cs 프로젝트: hadow/Commander
 public bool TryGetPackageContaining(string path, out IReadOnlyPackage package, out string filename)
 {
     return(modData.DefaultFileSystem.TryGetPackageContaining(path, out package, out filename));
 }
예제 #27
0
        bool IPackageLoader.TryParsePackage(Stream s, string filename, FileSystem context, out IReadOnlyPackage package)
        {
            // Take a peek at the file signature
            var signature = s.ReadASCII(4);

            s.Position -= 4;

            if (signature != "BIGF")
            {
                package = null;
                return(false);
            }

            package = new BigFile(s, filename);
            return(true);
        }
예제 #28
0
        public bool TryParsePackage(Stream stream, string filename, OpenRA.FileSystem.FileSystem filesystem, out IReadOnlyPackage package)
        {
            if (!filename.EndsWith(".stf"))
            {
                package = null;
                return(false);
            }

            package = new StfFile(stream, filename, filesystem);
            return(true);
        }
예제 #29
0
파일: FileSystem.cs 프로젝트: pchote/OpenRA
        public void Mount(IReadOnlyPackage package, string explicitName = null)
        {
            var mountCount = 0;
            if (mountedPackages.TryGetValue(package, out mountCount))
            {
                // Package is already mounted
                // Increment the mount count and bump up the file loading priority
                mountedPackages[package] = mountCount + 1;
                foreach (var filename in package.Contents)
                {
                    fileIndex[filename].Remove(package);
                    fileIndex[filename].Add(package);
                }
            }
            else
            {
                // Mounting the package for the first time
                mountedPackages.Add(package, 1);

                if (explicitName != null)
                    explicitMounts.Add(explicitName, package);

                foreach (var filename in package.Contents)
                    fileIndex[filename].Add(package);
            }
        }
예제 #30
0
        public Map(ModData modData, IReadOnlyPackage package)
        {
            this.modData = modData;
            Package      = package;

            if (!Package.Contains("map.yaml") || !Package.Contains("map.bin"))
            {
                throw new InvalidDataException("Not a valid map\n File: {0}".F(package.Name));
            }

            var yaml = new MiniYaml(null, MiniYaml.FromStream(Package.GetStream("map.yaml"), package.Name));

            foreach (var field in YamlFields)
            {
                field.Deserialize(this, yaml.Nodes);
            }

            if (MapFormat != SupportedMapFormat)
            {
                throw new InvalidDataException("Map format {0} is not supported.\n File: {1}".F(MapFormat, package.Name));
            }

            PlayerDefinitions = MiniYaml.NodesOrEmpty(yaml, "Players");
            ActorDefinitions  = MiniYaml.NodesOrEmpty(yaml, "Actors");

            Grid = modData.Manifest.Get <MapGrid>();

            var size = new Size(MapSize.X, MapSize.Y);

            Tiles     = new CellLayer <TerrainTile>(Grid.Type, size);
            Resources = new CellLayer <ResourceTile>(Grid.Type, size);
            Height    = new CellLayer <byte>(Grid.Type, size);

            using (var s = Package.GetStream("map.bin"))
            {
                var header = new BinaryDataHeader(s, MapSize);
                if (header.TilesOffset > 0)
                {
                    s.Position = header.TilesOffset;
                    for (var i = 0; i < MapSize.X; i++)
                    {
                        for (var j = 0; j < MapSize.Y; j++)
                        {
                            var tile  = s.ReadUInt16();
                            var index = s.ReadUInt8();

                            // TODO: Remember to remove this when rewriting tile variants / PickAny
                            if (index == byte.MaxValue)
                            {
                                index = (byte)(i % 4 + (j % 4) * 4);
                            }

                            Tiles[new MPos(i, j)] = new TerrainTile(tile, index);
                        }
                    }
                }

                if (header.ResourcesOffset > 0)
                {
                    s.Position = header.ResourcesOffset;
                    for (var i = 0; i < MapSize.X; i++)
                    {
                        for (var j = 0; j < MapSize.Y; j++)
                        {
                            var type    = s.ReadUInt8();
                            var density = s.ReadUInt8();
                            Resources[new MPos(i, j)] = new ResourceTile(type, density);
                        }
                    }
                }

                if (header.HeightsOffset > 0)
                {
                    s.Position = header.HeightsOffset;
                    for (var i = 0; i < MapSize.X; i++)
                    {
                        for (var j = 0; j < MapSize.Y; j++)
                        {
                            Height[new MPos(i, j)] = s.ReadUInt8().Clamp((byte)0, Grid.MaximumTerrainHeight);
                        }
                    }
                }
            }

            if (Grid.MaximumTerrainHeight > 0)
            {
                Tiles.CellEntryChanged  += UpdateProjection;
                Height.CellEntryChanged += UpdateProjection;
            }

            PostInit();

            Uid = ComputeUID(Package);
        }
예제 #31
0
파일: FileSystem.cs 프로젝트: pchote/OpenRA
        public IReadOnlyPackage OpenPackage(string filename, IReadOnlyPackage parent)
        {
            // HACK: limit support to zip and folder until we generalize the PackageLoader support
            if (filename.EndsWith(".zip", StringComparison.InvariantCultureIgnoreCase) ||
                filename.EndsWith(".oramap", StringComparison.InvariantCultureIgnoreCase))
            {
                using (var s = parent.GetStream(filename))
                    return new ZipFile(s, filename, parent);
            }

            if (parent is ZipFile)
                return new ZipFolder(this, (ZipFile)parent, filename, filename);

            if (parent is ZipFolder)
            {
                var folder = (ZipFolder)parent;
                return new ZipFolder(this, folder.Parent, folder.Name + "/" + filename, filename);
            }

            if (parent is Folder)
            {
                var subFolder = Platform.ResolvePath(Path.Combine(parent.Name, filename));
                if (Directory.Exists(subFolder))
                    return new Folder(subFolder);
            }

            return null;
        }
예제 #32
0
 public string GetPrefix(IReadOnlyPackage package)
 {
     return(explicitMounts.ContainsValue(package) ? explicitMounts.First(f => f.Value == package).Key : null);
 }
예제 #33
0
파일: FileSystem.cs 프로젝트: pchote/OpenRA
        public bool TryGetPackageContaining(string path, out IReadOnlyPackage package, out string filename)
        {
            var explicitSplit = path.IndexOf('|');
            if (explicitSplit > 0 && explicitMounts.TryGetValue(path.Substring(0, explicitSplit), out package))
            {
                filename = path.Substring(explicitSplit + 1);
                return true;
            }

            package = fileIndex[path].LastOrDefault(x => x.Contains(path));
            filename = path;

            return package != null;
        }
예제 #34
0
 public IReadOnlyPackage OpenPackage(string filename, IReadOnlyPackage parent)
 {
     // TODO: Make legacy callers access the parent package directly
     return(parent.OpenPackage(filename, this));
 }
예제 #35
0
파일: FileSystem.cs 프로젝트: pchote/OpenRA
        public bool Unmount(IReadOnlyPackage package)
        {
            var mountCount = 0;
            if (!mountedPackages.TryGetValue(package, out mountCount))
                return false;

            if (--mountCount <= 0)
            {
                foreach (var packagesForFile in fileIndex.Values)
                    packagesForFile.RemoveAll(p => p == package);

                mountedPackages.Remove(package);
                var explicitKeys = explicitMounts.Where(kv => kv.Value == package)
                    .Select(kv => kv.Key)
                    .ToList();

                foreach (var key in explicitKeys)
                    explicitMounts.Remove(key);

                // Mod packages aren't owned by us, so we shouldn't dispose them
                if (modPackages.Contains(package))
                    modPackages.Remove(package);
                else
                    package.Dispose();
            }
            else
                mountedPackages[package] = mountCount;

            return true;
        }