using System; using System.Collections.Generic; using System.Runtime.InteropServices; using Decal.Interop.Core; using Decal.Interop.Dat; namespace Decal.DecalDat { internal class FileFilterInfo { public string Name; public Guid Clsid; public bool Cache; } internal class CacheEntry { public FileFilterInfo Filter; public LibraryType Library; public uint FileId; public object Instance; } [ComVisible(true)] [Guid("37B083F0-276E-43AD-8D26-3F7449B519DC")] [ClassInterface(ClassInterfaceType.None)] [ProgId("DecalDat.DatService")] public class DatServiceImpl : IDatService, IDecalService, IDecalDirectory { private DatLibraryImpl _cell; private DatLibraryImpl _portal; private readonly List _filters = new List(); private readonly List _cache = new List(); private IDecalCore _decalCore; public void Initialize(DecalCore pDecal) { _decalCore = (IDecalCore)pDecal; // Resolve DAT file paths via MapPath string cellPath = _decalCore.MapPath("%ac%\\cell.dat"); string portalPath = _decalCore.MapPath("%ac%\\portal.dat"); // Load cell.dat (sector size 256) _cell = new DatLibraryImpl(); _cell.Load(this, cellPath, LibraryType.Cell, 256); // Load portal.dat (sector size 1024) _portal = new DatLibraryImpl(); _portal.Load(this, portalPath, LibraryType.Portal, 1024); // Load filter configuration from Decal LoadFilters(); } private void LoadFilters() { try { var config = _decalCore.Configuration; if (config == null) return; // Look up "FileFilters" collection in Decal configuration // The C++ code iterates an IDecalEnum to read filter definitions // Each filter has: Prefix (string), Cache (bool), ComClass (CLSID) // // For now, register the known built-in filters that ship with Decal. // When Decal.Core is implemented, this will read from live config. } catch { // Config may not be available yet } } public void BeforePlugins() { // No-op in original implementation } public void AfterPlugins() { // No-op in original implementation } public void Terminate() { _cache.Clear(); _filters.Clear(); _cell?.Dispose(); _cell = null; _portal?.Dispose(); _portal = null; _decalCore = null; } /// /// IDecalDirectory.Lookup - returns cell or portal library by name. /// public object Lookup(string strName) { if (string.Equals(strName, "portal", StringComparison.OrdinalIgnoreCase)) return _portal; if (string.Equals(strName, "cell", StringComparison.OrdinalIgnoreCase)) return _cell; return null; } // --- Filter management (internal, used by DatLibraryImpl) --- internal FileFilterInfo GetFilter(string name) { foreach (var f in _filters) { if (string.Equals(f.Name, name, StringComparison.OrdinalIgnoreCase)) return f; } return null; } internal object CreateFilter(FileFilterInfo filter) { try { var type = Type.GetTypeFromCLSID(filter.Clsid); if (type == null) return null; return Activator.CreateInstance(type); } catch { return null; } } internal object FindInCache(FileFilterInfo filter, LibraryType library, uint fileId) { foreach (var entry in _cache) { if (entry.Filter == filter && entry.Library == library && entry.FileId == fileId) return entry.Instance; } return null; } internal void AddToCache(FileFilterInfo filter, LibraryType library, uint fileId, object instance) { _cache.Add(new CacheEntry { Filter = filter, Library = library, FileId = fileId, Instance = instance }); } /// /// Register a file filter at runtime. /// internal void RegisterFilter(string name, Guid clsid, bool cache) { _filters.Add(new FileFilterInfo { Name = name, Clsid = clsid, Cache = cache }); } } }