Beispiel #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;
        }
Beispiel #2
0
        public ModData(string mod, bool useLoadScreen = false)
        {
            Languages = new string[0];
            Manifest = new Manifest(mod);
            ObjectCreator = new ObjectCreator(Manifest);
            Manifest.LoadCustomData(ObjectCreator);

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

            WidgetLoader = new WidgetLoader(this);
            RulesetCache = new RulesetCache(this);
            RulesetCache.LoadingProgress += HandleLoadingProgress;
            MapCache = new MapCache(this);

            var spriteLoaders = new List<ISpriteLoader>();
            foreach (var format in Manifest.SpriteFormats)
            {
                var loader = ObjectCreator.FindType(format + "Loader");
                if (loader == null || !loader.GetInterfaces().Contains(typeof(ISpriteLoader)))
                    throw new InvalidOperationException("Unable to find a sprite loader for type '{0}'.".F(format));

                spriteLoaders.Add((ISpriteLoader)ObjectCreator.CreateBasic(loader));
            }

            SpriteLoaders = spriteLoaders.ToArray();

            var sequenceFormat = Manifest.Get<SpriteSequenceFormat>();
            var sequenceLoader = ObjectCreator.FindType(sequenceFormat.Type + "Loader");
            var ctor = sequenceLoader != null ? sequenceLoader.GetConstructor(new[] { typeof(ModData) }) : null;
            if (sequenceLoader == null || !sequenceLoader.GetInterfaces().Contains(typeof(ISpriteSequenceLoader)) || ctor == null)
                throw new InvalidOperationException("Unable to find a sequence loader for type '{0}'.".F(sequenceFormat.Type));

            SpriteSequenceLoader = (ISpriteSequenceLoader)ctor.Invoke(new[] { this });
            SpriteSequenceLoader.OnMissingSpriteError = s => Log.Write("debug", s);

            // HACK: Mount only local folders so we have a half-working environment for the asset installer
            GlobalFileSystem.UnmountAll();
            foreach (var dir in Manifest.Folders)
                GlobalFileSystem.Mount(dir);

            defaultRules = Exts.Lazy(() => RulesetCache.Load());

            initialThreadId = System.Threading.Thread.CurrentThread.ManagedThreadId;
        }
Beispiel #3
0
        public ObjectCreator(Manifest manifest)
        {
            // All the core namespaces
            var asms = typeof(Game).Assembly.GetNamespaces() // Game
                .Select(c => Pair.New(typeof(Game).Assembly, c))
                .ToList();

            // Namespaces from each mod assembly
            foreach (var a in manifest.Assemblies)
            {
                var asm = Assembly.LoadFile(Path.GetFullPath(a));
                asms.AddRange(asm.GetNamespaces().Select(ns => Pair.New(asm, ns)));
            }

            assemblies = asms.ToArray();
        }
Beispiel #4
0
        public ModData(string mod)
        {
            Languages = new string[0];
            Manifest = new Manifest(mod);
            ObjectCreator = new ObjectCreator(Manifest);
            LoadScreen = ObjectCreator.CreateObject<ILoadScreen>(Manifest.LoadScreen.Value);
            LoadScreen.Init(Manifest, Manifest.LoadScreen.NodesDict.ToDictionary(x => x.Key, x => x.Value.Value));
            LoadScreen.Display();
            WidgetLoader = new WidgetLoader(this);
            RulesetCache = new RulesetCache(this);
            RulesetCache.LoadingProgress += HandleLoadingProgress;
            MapCache = new MapCache(this);

            // HACK: Mount only local folders so we have a half-working environment for the asset installer
            GlobalFileSystem.UnmountAll();
            foreach (var dir in Manifest.Folders)
                GlobalFileSystem.Mount(dir);

            defaultRules = Exts.Lazy(() => RulesetCache.LoadDefaultRules());

            initialThreadId = System.Threading.Thread.CurrentThread.ManagedThreadId;
        }
Beispiel #5
0
        public HotkeyManager(IReadOnlyFileSystem fileSystem, Dictionary <string, Hotkey> settings, Manifest manifest)
        {
            this.settings = settings;

            var keyDefinitions = MiniYaml.Load(fileSystem, manifest.Hotkeys, null);

            foreach (var kd in keyDefinitions)
            {
                var definition = new HotkeyDefinition(kd.Key, kd.Value);
                definitions[kd.Key] = definition;
                keys[kd.Key]        = definition.Default;
            }

            foreach (var kv in settings)
            {
                if (definitions.ContainsKey(kv.Key))
                {
                    keys[kv.Key] = kv.Value;
                }
            }

            foreach (var hd in definitions)
            {
                hd.Value.HasDuplicates = GetFirstDuplicate(hd.Value.Name, this[hd.Value.Name].GetValue(), hd.Value) != null;
            }
        }
Beispiel #6
0
		public static string MakeKey(Manifest mod) { return MakeKey(mod.Id, mod.Metadata.Version); }
Beispiel #7
0
		internal void Register(Manifest mod, string launchPath, IEnumerable<string> launchArgs, ModRegistration registration)
		{
			if (mod.Metadata.Hidden)
				return;

			var key = ExternalMod.MakeKey(mod);
			var yaml = new MiniYamlNode("Registration", new MiniYaml("", new List<MiniYamlNode>()
			{
				new MiniYamlNode("Id", mod.Id),
				new MiniYamlNode("Version", mod.Metadata.Version),
				new MiniYamlNode("Title", mod.Metadata.Title),
				new MiniYamlNode("LaunchPath", launchPath),
				new MiniYamlNode("LaunchArgs", new[] { "Game.Mod=" + mod.Id }.Concat(launchArgs).JoinWith(", "))
			}));

			using (var stream = mod.Package.GetStream("icon.png"))
				if (stream != null)
					yaml.Value.Nodes.Add(new MiniYamlNode("Icon", Convert.ToBase64String(stream.ReadAllBytes())));

			using (var stream = mod.Package.GetStream("icon-2x.png"))
				if (stream != null)
					yaml.Value.Nodes.Add(new MiniYamlNode("Icon2x", Convert.ToBase64String(stream.ReadAllBytes())));

			using (var stream = mod.Package.GetStream("icon-3x.png"))
				if (stream != null)
					yaml.Value.Nodes.Add(new MiniYamlNode("Icon3x", Convert.ToBase64String(stream.ReadAllBytes())));

			var sources = new List<string>();
			if (registration.HasFlag(ModRegistration.System))
				sources.Add(Platform.GetSupportDir(SupportDirType.System));

			if (registration.HasFlag(ModRegistration.User))
			{
				sources.Add(Platform.GetSupportDir(SupportDirType.User));

				// If using the modern support dir we must also write the registration
				// to the legacy support dir for older engine versions, but ONLY if it exists
				var legacyPath = Platform.GetSupportDir(SupportDirType.LegacyUser);
				if (Directory.Exists(legacyPath))
					sources.Add(legacyPath);
			}

			// Make sure the mod is available for this session, even if saving it fails
			LoadMod(yaml.Value, forceRegistration: true);

			var lines = new List<MiniYamlNode> { yaml }.ToLines().ToArray();
			foreach (var source in sources.Distinct())
			{
				var metadataPath = Path.Combine(source, "ModMetadata");

				try
				{
					Directory.CreateDirectory(metadataPath);
					File.WriteAllLines(Path.Combine(metadataPath, key + ".yaml"), lines);
				}
				catch (Exception e)
				{
					Log.Write("debug", "Failed to register current mod metadata");
					Log.Write("debug", e.ToString());
				}
			}
		}