Inheritance: IReadOnlyFileSystem
Esempio n. 1
0
        public ObjectCreator(Manifest manifest, FileSystem.FileSystem modFiles)
        {
            typeCache = new Cache <string, Type>(FindType);
            ctorCache = new Cache <Type, ConstructorInfo>(GetCtor);

            // Allow mods to load types from the core Game assembly, and any additional assemblies they specify.
            var assemblyList = new List <Assembly>()
            {
                typeof(Game).Assembly
            };

            foreach (var path in manifest.Assemblies)
            {
                var data = modFiles.Open(path).ReadAllBytes();

                // .NET doesn't provide any way of querying the metadata of an assembly without either:
                //   (a) loading duplicate data into the application domain, breaking the world.
                //   (b) crashing if the assembly has already been loaded.
                // We can't check the internal name of the assembly, so we'll work off the data instead
                var hash = CryptoUtil.SHA1Hash(data);

                Assembly assembly;
                if (!ResolvedAssemblies.TryGetValue(hash, out assembly))
                {
                    assembly = Assembly.Load(data);
                    ResolvedAssemblies.Add(hash, assembly);
                }

                assemblyList.Add(assembly);
            }

            AppDomain.CurrentDomain.AssemblyResolve += ResolveAssembly;
            assemblies = assemblyList.SelectMany(asm => asm.GetNamespaces().Select(ns => Pair.New(asm, ns))).ToArray();
            AppDomain.CurrentDomain.AssemblyResolve -= ResolveAssembly;
        }
Esempio n. 2
0
 public IReadOnlyPackage OpenPackage(string filename, FileSystem context)
 {
     return(Parent.OpenPackage(path + '/' + filename, context));
 }
Esempio n. 3
0
        public ModData(Manifest mod, InstalledMods mods, bool useLoadScreen = false)
        {
            Languages = Array.Empty <string>();

            // Take a local copy of the manifest
            Manifest       = new Manifest(mod.Id, mod.Package);
            ObjectCreator  = new ObjectCreator(Manifest, mods);
            PackageLoaders = ObjectCreator.GetLoaders <IPackageLoader>(Manifest.PackageFormats, "package");

            ModFiles = new FS(mod.Id, mods, PackageLoaders);
            ModFiles.LoadFromManifest(Manifest);
            Manifest.LoadCustomData(ObjectCreator);

            if (useLoadScreen)
            {
                LoadScreen = ObjectCreator.CreateObject <ILoadScreen>(Manifest.LoadScreen.Value);
                LoadScreen.Init(this, Manifest.LoadScreen.ToDictionary(my => my.Value));
                LoadScreen.Display();
            }

            WidgetLoader = new WidgetLoader(this);
            MapCache     = new MapCache(this);

            SoundLoaders  = ObjectCreator.GetLoaders <ISoundLoader>(Manifest.SoundFormats, "sound");
            SpriteLoaders = ObjectCreator.GetLoaders <ISpriteLoader>(Manifest.SpriteFormats, "sprite");
            VideoLoaders  = ObjectCreator.GetLoaders <IVideoLoader>(Manifest.VideoFormats, "video");

            var terrainFormat = Manifest.Get <TerrainFormat>();
            var terrainLoader = ObjectCreator.FindType(terrainFormat.Type + "Loader");
            var terrainCtor   = terrainLoader?.GetConstructor(new[] { typeof(ModData) });

            if (terrainLoader == null || !terrainLoader.GetInterfaces().Contains(typeof(ITerrainLoader)) || terrainCtor == null)
            {
                throw new InvalidOperationException($"Unable to find a terrain loader for type '{terrainFormat.Type}'.");
            }

            TerrainLoader = (ITerrainLoader)terrainCtor.Invoke(new[] { this });

            var sequenceFormat = Manifest.Get <SpriteSequenceFormat>();
            var sequenceLoader = ObjectCreator.FindType(sequenceFormat.Type + "Loader");
            var sequenceCtor   = sequenceLoader != null?sequenceLoader.GetConstructor(new[] { typeof(ModData) }) : null;

            if (sequenceLoader == null || !sequenceLoader.GetInterfaces().Contains(typeof(ISpriteSequenceLoader)) || sequenceCtor == null)
            {
                throw new InvalidOperationException($"Unable to find a sequence loader for type '{sequenceFormat.Type}'.");
            }

            SpriteSequenceLoader = (ISpriteSequenceLoader)sequenceCtor.Invoke(new[] { this });

            var modelFormat = Manifest.Get <ModelSequenceFormat>();
            var modelLoader = ObjectCreator.FindType(modelFormat.Type + "Loader");
            var modelCtor   = modelLoader != null?modelLoader.GetConstructor(new[] { typeof(ModData) }) : null;

            if (modelLoader == null || !modelLoader.GetInterfaces().Contains(typeof(IModelSequenceLoader)) || modelCtor == null)
            {
                throw new InvalidOperationException($"Unable to find a model loader for type '{modelFormat.Type}'.");
            }

            ModelSequenceLoader = (IModelSequenceLoader)modelCtor.Invoke(new[] { this });
            ModelSequenceLoader.OnMissingModelError = s => Log.Write("debug", s);

            Hotkeys = new HotkeyManager(ModFiles, Game.Settings.Keys, Manifest);

            defaultRules       = Exts.Lazy(() => Ruleset.LoadDefaults(this));
            defaultTerrainInfo = Exts.Lazy(() =>
            {
                var items = new Dictionary <string, ITerrainInfo>();

                foreach (var file in Manifest.TileSets)
                {
                    var t = TerrainLoader.ParseTerrain(DefaultFileSystem, file);
                    items.Add(t.Id, t);
                }

                return((IReadOnlyDictionary <string, ITerrainInfo>)(new ReadOnlyDictionary <string, ITerrainInfo>(items)));
            });

            defaultSequences = Exts.Lazy(() =>
            {
                var items = DefaultTerrainInfo.ToDictionary(t => t.Key, t => new SequenceProvider(DefaultFileSystem, this, t.Key, null));
                return((IReadOnlyDictionary <string, SequenceProvider>)(new ReadOnlyDictionary <string, SequenceProvider>(items)));
            });

            initialThreadId = Environment.CurrentManagedThreadId;
        }
Esempio n. 4
0
 public IReadOnlyPackage OpenPackage(string filename, FileSystem context)
 {
     // Not implemented
     return(null);
 }
Esempio n. 5
0
 public bool TryParsePackage(Stream s, string filename, OpenRA.FileSystem.FileSystem context, out IReadOnlyPackage package)
 {
     package = new DataFile(s, filename);
     return(true);
 }
Esempio n. 6
0
 public IReadOnlyPackage OpenPackage(string filename, OpenRA.FileSystem.FileSystem context)
 {
     return(null);
 }
Esempio n. 7
0
            public LvlPackage(Stream s, string filename, FS context)
            {
                stream = s;
                Name   = filename;

                var lvlLookup    = new Dictionary <string, string>();
                var updateLookup = false;

                Stream s2;

                if (context.TryOpen(filename + ".yaml", out s2))
                {
                    lvlLookup = MiniYaml.FromStream(s2).ToDictionary(x => x.Key, x => x.Value.Value);
                }

                var fileTypeListOffset = s.ReadUInt32();

                s.Position = fileTypeListOffset;

                uint firstFileListOffset = 0;

                for (var i = 0; s.Position < s.Length; i++)
                {
                    s.Position = fileTypeListOffset + i * 8;

                    var fileType       = s.ReadASCII(4);
                    var fileListOffset = s.ReadUInt32();

                    // List terminator reached.
                    if (fileListOffset == 0)
                    {
                        break;
                    }

                    // We need this to calculate the last fileLength.
                    if (firstFileListOffset == 0)
                    {
                        firstFileListOffset = fileListOffset;
                    }

                    // To determine when this list ends, check the next entry
                    s.Position += 4;
                    var fileListEndOffset = s.ReadUInt32();

                    // List terminator reached, so assume the list goes on till the fileTypeList starts.
                    if (fileListEndOffset == 0)
                    {
                        fileListEndOffset = fileTypeListOffset;
                    }

                    s.Position = fileListOffset;

                    for (var j = 0; s.Position < fileListEndOffset; j++)
                    {
                        var fileOffset = s.ReadUInt32();

                        // Removed file, still increments fileId.
                        if (fileOffset == 0)
                        {
                            continue;
                        }

                        // As the fileLength is nowhere stored, but files always follow in order, calculate the previous fileLength.
                        if (index.Count > 0)
                        {
                            var entry = index.ElementAt(index.Count - 1).Value;
                            entry[1] = fileOffset - entry[0];
                        }

                        var assetFileName = j + "." + fileType.ToLower();

                        // Lookup assumed original filename for better readability in yaml files.
                        if (lvlLookup.ContainsKey(assetFileName))
                        {
                            assetFileName = lvlLookup[assetFileName];
                        }
                        else
                        {
                            lvlLookup.Add(assetFileName, assetFileName);
                            updateLookup = true;
                        }

                        index.Add(assetFileName, new uint[] { fileOffset, 0 });
                    }
                }

                // Calculate the last fileLength.
                if (index.Count > 0)
                {
                    var entry = index.ElementAt(index.Count - 1).Value;
                    entry[1] = firstFileListOffset - entry[0];
                }

                if (updateLookup)
                {
                    File.WriteAllText(filename + ".yaml",
                                      lvlLookup.Select(e => e.Key + ": " + e.Value).JoinWith("\n") + "\n");
                }

                /*if (!Directory.Exists("XTRACT/" + filename))
                 *      Directory.CreateDirectory("XTRACT/" + filename);
                 *
                 * foreach (var entry in index)
                 * {
                 *      stream.Position = entry.Value[0];
                 *      File.WriteAllBytes("XTRACT/" + filename + "/" + entry.Key, stream.ReadBytes((int)entry.Value[1]));
                 * }*/
            }
Esempio n. 8
0
        public ModContentLogic(Widget widget, ModData modData, Manifest mod, ModContent content, Action onCancel)
        {
            this.content = content;

            var panel = widget.Get("CONTENT_PANEL");

            var modObjectCreator  = new ObjectCreator(mod, Game.Mods);
            var modPackageLoaders = modObjectCreator.GetLoaders <IPackageLoader>(mod.PackageFormats, "package");
            var modFileSystem     = new FS(mod.Id, Game.Mods, modPackageLoaders);

            modFileSystem.LoadFromManifest(mod);

            var sourceYaml = MiniYaml.Load(modFileSystem, content.Sources, null);

            foreach (var s in sourceYaml)
            {
                sources.Add(s.Key, new ModContent.ModSource(s.Value));
            }

            var downloadYaml = MiniYaml.Load(modFileSystem, content.Downloads, null);

            foreach (var d in downloadYaml)
            {
                downloads.Add(d.Key, new ModContent.ModDownload(d.Value));
            }

            modFileSystem.UnmountAll();

            scrollPanel = panel.Get <ScrollPanelWidget>("PACKAGES");
            template    = scrollPanel.Get <ContainerWidget>("PACKAGE_TEMPLATE");

            var headerTemplate = panel.Get <LabelWidget>("HEADER_TEMPLATE");
            var headerLines    = !string.IsNullOrEmpty(content.HeaderMessage) ? content.HeaderMessage.Replace("\\n", "\n").Split('\n') : new string[0];
            var headerHeight   = 0;

            foreach (var l in headerLines)
            {
                var line = (LabelWidget)headerTemplate.Clone();
                line.GetText   = () => l;
                line.Bounds.Y += headerHeight;
                panel.AddChild(line);

                headerHeight += headerTemplate.Bounds.Height;
            }

            panel.Bounds.Height  += headerHeight;
            panel.Bounds.Y       -= headerHeight / 2;
            scrollPanel.Bounds.Y += headerHeight;

            var discButton = panel.Get <ButtonWidget>("CHECK_DISC_BUTTON");

            discButton.Bounds.Y += headerHeight;
            discButton.IsVisible = () => discAvailable;

            discButton.OnClick = () => Ui.OpenWindow("DISC_INSTALL_PANEL", new WidgetArgs
            {
                { "afterInstall", () => { } },
                { "sources", sources },
                { "content", content }
            });

            var backButton = panel.Get <ButtonWidget>("BACK_BUTTON");

            backButton.Bounds.Y += headerHeight;
            backButton.OnClick   = () => { Ui.CloseWindow(); onCancel(); };

            PopulateContentList();
            Game.RunAfterTick(Ui.ResetTooltips);
        }
Esempio n. 9
0
        public ModContentPromptLogic(Widget widget, ModData modData, Manifest mod, ModContent content, Action continueLoading)
        {
            this.content = content;
            CheckRequiredContentInstalled();

            var panel          = widget.Get("CONTENT_PROMPT_PANEL");
            var headerTemplate = panel.Get <LabelWidget>("HEADER_TEMPLATE");
            var headerLines    = !string.IsNullOrEmpty(content.InstallPromptMessage) ? content.InstallPromptMessage.Replace("\\n", "\n").Split('\n') : new string[0];
            var headerHeight   = 0;

            foreach (var l in headerLines)
            {
                var line = (LabelWidget)headerTemplate.Clone();
                line.GetText   = () => l;
                line.Bounds.Y += headerHeight;
                panel.AddChild(line);

                headerHeight += headerTemplate.Bounds.Height;
            }

            panel.Bounds.Height += headerHeight;
            panel.Bounds.Y      -= headerHeight / 2;

            var advancedButton = panel.Get <ButtonWidget>("ADVANCED_BUTTON");

            advancedButton.Bounds.Y += headerHeight;
            advancedButton.OnClick   = () =>
            {
                Ui.OpenWindow("CONTENT_PANEL", new WidgetArgs
                {
                    { "mod", mod },
                    { "content", content },
                    { "onCancel", CheckRequiredContentInstalled }
                });
            };

            var quickButton = panel.Get <ButtonWidget>("QUICK_BUTTON");

            quickButton.IsVisible = () => !string.IsNullOrEmpty(content.QuickDownload);
            quickButton.Bounds.Y += headerHeight;
            quickButton.OnClick   = () =>
            {
                var modObjectCreator  = new ObjectCreator(mod, Game.Mods);
                var modPackageLoaders = modObjectCreator.GetLoaders <IPackageLoader>(mod.PackageFormats, "package");
                var modFileSystem     = new FS(Game.Mods, modPackageLoaders);
                modFileSystem.LoadFromManifest(mod);

                var downloadYaml = MiniYaml.Load(modFileSystem, content.Downloads, null);
                modFileSystem.UnmountAll();

                var download = downloadYaml.FirstOrDefault(n => n.Key == content.QuickDownload);
                if (download == null)
                {
                    throw new InvalidOperationException("Mod QuickDownload `{0}` definition not found.".F(content.QuickDownload));
                }

                Ui.OpenWindow("PACKAGE_DOWNLOAD_PANEL", new WidgetArgs
                {
                    { "download", new ModContent.ModDownload(download.Value) },
                    { "onSuccess", continueLoading }
                });
            };

            var quitButton = panel.Get <ButtonWidget>("QUIT_BUTTON");

            quitButton.GetText   = () => requiredContentInstalled ? "Continue" : "Quit";
            quitButton.Bounds.Y += headerHeight;
            quitButton.OnClick   = () =>
            {
                if (requiredContentInstalled)
                {
                    continueLoading();
                }
                else
                {
                    Game.Exit();
                }
            };

            Game.RunAfterTick(Ui.ResetTooltips);
        }